summary refs log tree commit diff
path: root/pkgs/servers/http/nginx/nix-etag-1.15.4.patch
blob: d001b842f335fcdcbe9b8a5efd111f3de3812cdc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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
--- 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)
 {
     ngx_table_elt_t           *etag;
     ngx_http_core_loc_conf_t  *clcf;
+    u_char                    *real, *ptr1, *ptr2;
+    ngx_err_t                 err;
 
     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;
     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;
+    err = ngx_errno;
+    real = ngx_realpath(clcf->root.data, NULL);
+    ngx_set_errno(err);
+
+    #define NIX_STORE_DIR "@nixStoreDir@"
+    #define NIX_STORE_LEN @nixStoreDirLen@
+
+    if (r->headers_out.last_modified_time == 1
+        && real != NULL
+        && !ngx_strncmp(real, NIX_STORE_DIR, NIX_STORE_LEN)
+        && real[NIX_STORE_LEN] == '/'
+        && real[NIX_STORE_LEN + 1] != '\0')
+    {
+        ptr1 = real + NIX_STORE_LEN;
+        *ptr1 = '"';
+
+        ptr2 = (u_char *) ngx_strchr(ptr1, '-');
+
+        if (ptr2 == NULL) {
+            ngx_free(real);
+            etag->hash = 0;
+            return NGX_ERROR;
+        }
+
+        *ptr2++ = '"';
+        *ptr2 = '\0';
+
+        etag->value.len = ngx_strlen(ptr1);
+        etag->value.data = ngx_pnalloc(r->pool, etag->value.len);
+
+        if (etag->value.data == NULL) {
+            ngx_free(real);
+            etag->hash = 0;
+            return NGX_ERROR;
+        }
+
+        ngx_memcpy(etag->value.data, ptr1, etag->value.len);
+        ngx_http_clear_last_modified(r);
+    } else {
+        etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3);
+
+        if (etag->value.data == NULL) {
+            ngx_free(real);
+            etag->hash = 0;
+            return NGX_ERROR;
+        }
+
+        etag->value.len = ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
+                                      r->headers_out.last_modified_time,
+                                      r->headers_out.content_length_n)
+                          - etag->value.data;
     }
 
-    etag->value.len = ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
-                                  r->headers_out.last_modified_time,
-                                  r->headers_out.content_length_n)
-                      - etag->value.data;
+    ngx_free(real);
 
     r->headers_out.etag = etag;