[PATCH] append "-gzip" to etags processed by gzip_filter_module + not modified support

Andrew Williams sobakasu at gmail.com
Wed May 28 06:56:04 UTC 2014


this patch modifies the etag header returned by responses processed by
the gzip filter, appending "-gzip" to the etag (instead of deleting
it). Also, If-None-Match and If-Match requests work against the
modified etag.
(the gunzip module appends "-gunzip" to the etag).

cheers
Andrew

# HG changeset patch
# User Andrew Williams <sobakasu at gmail.com>
# Date 1401259215 -34200
#      Wed May 28 16:10:15 2014 +0930
# Node ID 102149a95d84250e709051b1f2c8b49a1872bd3e
# Parent  adb742cf27f771771b293cc280f594038e8d9aab
append "-gzip" to etags processed by gzip_filter_module + not modified support

diff -r adb742cf27f7 -r 102149a95d84
src/http/modules/ngx_http_gunzip_filter_module.c
--- a/src/http/modules/ngx_http_gunzip_filter_module.c Tue May 27
17:58:09 2014 +0400
+++ b/src/http/modules/ngx_http_gunzip_filter_module.c Wed May 28
16:10:15 2014 +0930
@@ -115,6 +115,7 @@

 static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
 static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
+static ngx_str_t  ngx_http_gunzip_etag_suffix = ngx_string("-gunzip");


 static ngx_int_t
@@ -149,6 +150,13 @@
         return ngx_http_next_header_filter(r);
     }

+    ngx_int_t etag_filter_result;
+    ngx_http_update_etag(r, &ngx_http_gunzip_etag_suffix);
+    if (ngx_http_test_etag_if_match(r, ngx_http_next_header_filter,
+    &etag_filter_result)) {
+ return etag_filter_result;
+    }
+
     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gunzip_ctx_t));
     if (ctx == NULL) {
         return NGX_ERROR;
@@ -165,7 +173,6 @@

     ngx_http_clear_content_length(r);
     ngx_http_clear_accept_ranges(r);
-    ngx_http_clear_etag(r);

     return ngx_http_next_header_filter(r);
 }
diff -r adb742cf27f7 -r 102149a95d84
src/http/modules/ngx_http_gzip_filter_module.c
--- a/src/http/modules/ngx_http_gzip_filter_module.c Tue May 27
17:58:09 2014 +0400
+++ b/src/http/modules/ngx_http_gzip_filter_module.c Wed May 28
16:10:15 2014 +0930
@@ -229,6 +229,7 @@


 static ngx_str_t  ngx_http_gzip_ratio = ngx_string("gzip_ratio");
+static ngx_str_t  ngx_http_gzip_etag_suffix = ngx_string("-gzip");

 static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
 static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
@@ -280,6 +281,13 @@
         return ngx_http_next_header_filter(r);
     }

+    ngx_int_t etag_filter_result;
+    ngx_http_update_etag(r, &ngx_http_gzip_etag_suffix);
+    if (ngx_http_test_etag_if_match(r, ngx_http_next_header_filter,
+    &etag_filter_result)) {
+ return etag_filter_result;
+    }
+
     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gzip_ctx_t));
     if (ctx == NULL) {
         return NGX_ERROR;
@@ -306,7 +314,6 @@

     ngx_http_clear_content_length(r);
     ngx_http_clear_accept_ranges(r);
-    ngx_http_clear_etag(r);

     return ngx_http_next_header_filter(r);
 }
diff -r adb742cf27f7 -r 102149a95d84
src/http/modules/ngx_http_not_modified_filter_module.c
--- a/src/http/modules/ngx_http_not_modified_filter_module.c Tue May
27 17:58:09 2014 +0400
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c Wed May
28 16:10:15 2014 +0930
@@ -12,8 +12,6 @@

 static ngx_uint_t ngx_http_test_if_unmodified(ngx_http_request_t *r);
 static ngx_uint_t ngx_http_test_if_modified(ngx_http_request_t *r);
-static ngx_uint_t ngx_http_test_if_match(ngx_http_request_t *r,
-    ngx_table_elt_t *header);
 static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf);


@@ -160,76 +158,6 @@
 }


-static ngx_uint_t
-ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header)
-{
-    u_char     *start, *end, ch;
-    ngx_str_t  *etag, *list;
-
-    list = &header->value;
-
-    if (list->len == 1 && list->data[0] == '*') {
-        return 1;
-    }
-
-    if (r->headers_out.etag == NULL) {
-        return 0;
-    }
-
-    etag = &r->headers_out.etag->value;
-
-    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http im:\"%V\" etag:%V", list, etag);
-
-    start = list->data;
-    end = list->data + list->len;
-
-    while (start < end) {
-
-        if (etag->len > (size_t) (end - start)) {
-            return 0;
-        }
-
-        if (ngx_strncmp(start, etag->data, etag->len) != 0) {
-            goto skip;
-        }
-
-        start += etag->len;
-
-        while (start < end) {
-            ch = *start;
-
-            if (ch == ' ' || ch == '\t') {
-                start++;
-                continue;
-            }
-
-            break;
-        }
-
-        if (start == end || *start == ',') {
-            return 1;
-        }
-
-    skip:
-
-        while (start < end && *start != ',') { start++; }
-        while (start < end) {
-            ch = *start;
-
-            if (ch == ' ' || ch == '\t' || ch == ',') {
-                start++;
-                continue;
-            }
-
-            break;
-        }
-    }
-
-    return 0;
-}
-
-
 static ngx_int_t
 ngx_http_not_modified_filter_init(ngx_conf_t *cf)
 {
diff -r adb742cf27f7 -r 102149a95d84 src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c Tue May 27 17:58:09 2014 +0400
+++ b/src/http/ngx_http_core_module.c Wed May 28 16:10:15 2014 +0930
@@ -1851,6 +1851,134 @@
 }


+// update etag, append suffix
+ngx_uint_t
+ngx_http_update_etag(ngx_http_request_t *r, ngx_str_t *suffix)
+{
+    ngx_table_elt_t           *etag;
+    void *old_etag_value;
+
+    etag = r->headers_out.etag;
+
+    if (etag == NULL || suffix == NULL)
+ return 0;
+
+    old_etag_value = etag->value.data;
+    etag->value.data = ngx_pnalloc(r->pool, etag->value.len +
+   suffix->len + 1);
+    ngx_cpystrn(etag->value.data, old_etag_value, etag->value.len);
+    etag->value.len = ngx_sprintf(etag->value.data + etag->value.len - 1,
+  "%s\"", suffix->data) - etag->value.data;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+   "http updated etag: %s", etag->value.data);
+
+    return 1;
+}
+
+
+ngx_int_t
+ngx_http_test_etag_if_match(ngx_http_request_t *r,
+    ngx_http_output_header_filter_pt next_header_filter,
+    ngx_int_t *etag_filter_result)
+{
+    if (r->headers_in.if_match
+ && !ngx_http_test_if_match(r, r->headers_in.if_match)) {
+        *etag_filter_result = ngx_http_filter_finalize_request
+    (r, NULL, NGX_HTTP_PRECONDITION_FAILED);
+ return 1;
+    }
+    else if (r->headers_in.if_none_match
+     && ngx_http_test_if_match(r, r->headers_in.if_none_match)) {
+        /* not modified */
+        r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
+        r->headers_out.status_line.len = 0;
+        r->headers_out.content_type.len = 0;
+        ngx_http_clear_content_length(r);
+        ngx_http_clear_accept_ranges(r);
+
+        if (r->headers_out.content_encoding) {
+            r->headers_out.content_encoding->hash = 0;
+            r->headers_out.content_encoding = NULL;
+        }
+
+        *etag_filter_result = next_header_filter(r);
+ return 1;
+    }
+    return 0;
+}
+
+
+ngx_uint_t
+ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header)
+{
+    u_char     *start, *end, ch;
+    ngx_str_t  *etag, *list;
+
+    list = &header->value;
+
+    if (list->len == 1 && list->data[0] == '*') {
+        return 1;
+    }
+
+    if (r->headers_out.etag == NULL) {
+        return 0;
+    }
+
+    etag = &r->headers_out.etag->value;
+
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http im:\"%V\" etag:%V", list, etag);
+
+    start = list->data;
+    end = list->data + list->len;
+
+    while (start < end) {
+
+        if (etag->len > (size_t) (end - start)) {
+            return 0;
+        }
+
+        if (ngx_strncmp(start, etag->data, etag->len) != 0) {
+            goto skip;
+        }
+
+        start += etag->len;
+
+        while (start < end) {
+            ch = *start;
+
+            if (ch == ' ' || ch == '\t') {
+                start++;
+                continue;
+            }
+
+            break;
+        }
+
+        if (start == end || *start == ',') {
+            return 1;
+        }
+
+    skip:
+
+        while (start < end && *start != ',') { start++; }
+        while (start < end) {
+            ch = *start;
+
+            if (ch == ' ' || ch == '\t' || ch == ',') {
+                start++;
+                continue;
+            }
+
+            break;
+        }
+    }
+
+    return 0;
+}
+
+
 ngx_int_t
 ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
     ngx_str_t *ct, ngx_http_complex_value_t *cv)
diff -r adb742cf27f7 -r 102149a95d84 src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h Tue May 27 17:58:09 2014 +0400
+++ b/src/http/ngx_http_core_module.h Wed May 28 16:10:15 2014 +0930
@@ -500,7 +500,6 @@
 void *ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t
*types_hash);
 ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r);
 void ngx_http_set_exten(ngx_http_request_t *r);
-ngx_int_t ngx_http_set_etag(ngx_http_request_t *r);
 ngx_int_t ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
     ngx_str_t *ct, ngx_http_complex_value_t *cv);
 u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name,
@@ -527,6 +526,15 @@
     (ngx_http_request_t *r, ngx_chain_t *chain);


+ngx_int_t ngx_http_set_etag(ngx_http_request_t *r);
+ngx_uint_t ngx_http_update_etag(ngx_http_request_t *r, ngx_str_t *suffix);
+ngx_int_t ngx_http_test_etag_if_match(ngx_http_request_t *r,
+    ngx_http_output_header_filter_pt next_header_filter,
+    ngx_int_t *etag_filter_result);
+ngx_uint_t ngx_http_test_if_match(ngx_http_request_t *r,
+    ngx_table_elt_t *header);
+
+
 ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *chain);
 ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *chain);



More information about the nginx-devel mailing list