about summary refs log tree commit diff
path: root/nixpkgs/pkgs/servers/http/nginx/nix-etag-1.15.4.patch
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/servers/http/nginx/nix-etag-1.15.4.patch')
-rw-r--r--nixpkgs/pkgs/servers/http/nginx/nix-etag-1.15.4.patch43
1 files changed, 32 insertions, 11 deletions
diff --git a/nixpkgs/pkgs/servers/http/nginx/nix-etag-1.15.4.patch b/nixpkgs/pkgs/servers/http/nginx/nix-etag-1.15.4.patch
index d001b842f335..8c8c8ce74b21 100644
--- a/nixpkgs/pkgs/servers/http/nginx/nix-etag-1.15.4.patch
+++ b/nixpkgs/pkgs/servers/http/nginx/nix-etag-1.15.4.patch
@@ -2,10 +2,10 @@ This patch makes it possible to serve static content from Nix store paths, by
 using the hash of the store path for the ETag header.
 
 diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
-index cb49ef74..7b456993 100644
+index 97a91aee2..2d07d71e6 100644
 --- a/src/http/ngx_http_core_module.c
 +++ b/src/http/ngx_http_core_module.c
-@@ -1583,6 +1583,8 @@ ngx_http_set_etag(ngx_http_request_t *r)
+@@ -1676,6 +1676,8 @@ ngx_http_set_etag(ngx_http_request_t *r)
  {
      ngx_table_elt_t           *etag;
      ngx_http_core_loc_conf_t  *clcf;
@@ -14,14 +14,25 @@ index cb49ef74..7b456993 100644
  
      clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
  
-@@ -1598,16 +1600,60 @@ ngx_http_set_etag(ngx_http_request_t *r)
-     etag->hash = 1;
+@@ -1692,16 +1694,82 @@ ngx_http_set_etag(ngx_http_request_t *r)
+     etag->next = NULL;
      ngx_str_set(&etag->key, "ETag");
  
 -    etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3);
 -    if (etag->value.data == NULL) {
 -        etag->hash = 0;
 -        return NGX_ERROR;
++    // Upstream nginx uses file mod timestamp and content-length for Etag, but
++    // files in the Nix store have their timestamps reset, so that doesn't work.
++    // Instead, when serving from the Nix store, we use the hash from the store
++    // path and content-length.
++    //
++    // Every file in under the given store path will share the same store path
++    // hash. It is fine to serve different resources with the same Etag, but
++    // different representations of the same resource (eg the same file, but
++    // gzip-compressed) should have different Etags. Thus, we also append
++    // content-length, which should be different when the response is compressed
++
 +    err = ngx_errno;
 +    real = ngx_realpath(clcf->root.data, NULL);
 +    ngx_set_errno(err);
@@ -35,8 +46,10 @@ index cb49ef74..7b456993 100644
 +        && real[NIX_STORE_LEN] == '/'
 +        && real[NIX_STORE_LEN + 1] != '\0')
 +    {
-+        ptr1 = real + NIX_STORE_LEN;
-+        *ptr1 = '"';
++        // extract the hash from a path formatted like
++        // /nix/store/hashhere1234-pname-1.0.0
++        // +1 to skip the leading /
++        ptr1 = real + NIX_STORE_LEN + 1;
 +
 +        ptr2 = (u_char *) ngx_strchr(ptr1, '-');
 +
@@ -46,11 +59,11 @@ index cb49ef74..7b456993 100644
 +            return NGX_ERROR;
 +        }
 +
-+        *ptr2++ = '"';
 +        *ptr2 = '\0';
 +
-+        etag->value.len = ngx_strlen(ptr1);
-+        etag->value.data = ngx_pnalloc(r->pool, etag->value.len);
++        // hash + content-length + quotes and hyphen. Note that the
++        // content-length part of the string can vary in length.
++        etag->value.data = ngx_pnalloc(r->pool, ngx_strlen(ptr1) + NGX_OFF_T_LEN + 3);
 +
 +        if (etag->value.data == NULL) {
 +            ngx_free(real);
@@ -58,9 +71,18 @@ index cb49ef74..7b456993 100644
 +            return NGX_ERROR;
 +        }
 +
-+        ngx_memcpy(etag->value.data, ptr1, etag->value.len);
++
++        // set value.data content to "{hash}-{content-length}" (including quote
++        // marks), and set value.len to the length of the resulting string
++        etag->value.len = ngx_sprintf(etag->value.data, "\"\%s-%xO\"",
++                                      ptr1,
++                                      r->headers_out.content_length_n)
++                          - etag->value.data;
++
 +        ngx_http_clear_last_modified(r);
 +    } else {
++        // outside of Nix store, use the upstream Nginx logic for etags
++
 +        etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3);
 +
 +        if (etag->value.data == NULL) {
@@ -82,4 +104,3 @@ index cb49ef74..7b456993 100644
 +    ngx_free(real);
  
      r->headers_out.etag = etag;
-