# HG changeset patch
# User "Aaron Peschel <aaron.peschel@gmail.com>"
# Date 1382665837 25200
#      Thu Oct 24 18:50:37 2013 -0700
# Node ID bc78c038fddf40230f5fe8997b24764d6c1c5b2f
# Parent  e6a1623f87bc96d5ec62b6d77356aa47dbc60756
Add Support for Weak ETags

This is a response to rev 4746 which removed ETags. 4746 removes the ETag field
from the header in all instances where content is modified by the web server
prior to being sent to the requesting client. This is far more stringent than
required by the HTTP spec.

The HTTP spec requires that strict ETags be dependent on the variant that is
returned by the server. While removing all ETags from these variants
*technically* meets the spec, it is a bit extreme.

This commit modifies the ngx_http_clear_etag macro to check if the ETag is
marked as a weak ETag. IFF that case, the ETag is retained, and not dropped.

Longer term, a better solution would be to completely remove
ngx_http_clear_strict_etag and replace it with functions to generate a strict
ETag for a variant prior to sending a response to the client, provided that
there is not a weak ETag field already included.

diff -r e6a1623f87bc -r bc78c038fddf src/http/modules/ngx_http_addition_filter_module.c
--- a/src/http/modules/ngx_http_addition_filter_module.c	Mon Oct 21 18:20:32 2013 +0800
+++ b/src/http/modules/ngx_http_addition_filter_module.c	Thu Oct 24 18:50:37 2013 -0700
@@ -121,7 +121,7 @@
 
     ngx_http_clear_content_length(r);
     ngx_http_clear_accept_ranges(r);
-    ngx_http_clear_etag(r);
+    ngx_http_clear_strict_etag(r);
 
     return ngx_http_next_header_filter(r);
 }
diff -r e6a1623f87bc -r bc78c038fddf src/http/modules/ngx_http_gunzip_filter_module.c
--- a/src/http/modules/ngx_http_gunzip_filter_module.c	Mon Oct 21 18:20:32 2013 +0800
+++ b/src/http/modules/ngx_http_gunzip_filter_module.c	Thu Oct 24 18:50:37 2013 -0700
@@ -165,7 +165,7 @@
 
     ngx_http_clear_content_length(r);
     ngx_http_clear_accept_ranges(r);
-    ngx_http_clear_etag(r);
+    ngx_http_clear_strict_etag(r);
 
     return ngx_http_next_header_filter(r);
 }
diff -r e6a1623f87bc -r bc78c038fddf src/http/modules/ngx_http_gzip_filter_module.c
--- a/src/http/modules/ngx_http_gzip_filter_module.c	Mon Oct 21 18:20:32 2013 +0800
+++ b/src/http/modules/ngx_http_gzip_filter_module.c	Thu Oct 24 18:50:37 2013 -0700
@@ -306,7 +306,7 @@
 
     ngx_http_clear_content_length(r);
     ngx_http_clear_accept_ranges(r);
-    ngx_http_clear_etag(r);
+    ngx_http_clear_strict_etag(r);
 
     return ngx_http_next_header_filter(r);
 }
diff -r e6a1623f87bc -r bc78c038fddf src/http/modules/ngx_http_ssi_filter_module.c
--- a/src/http/modules/ngx_http_ssi_filter_module.c	Mon Oct 21 18:20:32 2013 +0800
+++ b/src/http/modules/ngx_http_ssi_filter_module.c	Thu Oct 24 18:50:37 2013 -0700
@@ -368,7 +368,7 @@
     if (r == r->main) {
         ngx_http_clear_content_length(r);
         ngx_http_clear_accept_ranges(r);
-        ngx_http_clear_etag(r);
+        ngx_http_clear_strict_etag(r);
 
         if (!slcf->last_modified) {
             ngx_http_clear_last_modified(r);
diff -r e6a1623f87bc -r bc78c038fddf src/http/modules/ngx_http_sub_filter_module.c
--- a/src/http/modules/ngx_http_sub_filter_module.c	Mon Oct 21 18:20:32 2013 +0800
+++ b/src/http/modules/ngx_http_sub_filter_module.c	Thu Oct 24 18:50:37 2013 -0700
@@ -175,7 +175,7 @@
 
     if (r == r->main) {
         ngx_http_clear_content_length(r);
-        ngx_http_clear_etag(r);
+        ngx_http_clear_strict_etag(r);
 
         if (!slcf->last_modified) {
             ngx_http_clear_last_modified(r);
diff -r e6a1623f87bc -r bc78c038fddf src/http/modules/ngx_http_xslt_filter_module.c
--- a/src/http/modules/ngx_http_xslt_filter_module.c	Mon Oct 21 18:20:32 2013 +0800
+++ b/src/http/modules/ngx_http_xslt_filter_module.c	Thu Oct 24 18:50:37 2013 -0700
@@ -337,7 +337,7 @@
             r->headers_out.content_length = NULL;
         }
 
-        ngx_http_clear_etag(r);
+        ngx_http_clear_strict_etag(r);
 
         conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module);
 
diff -r e6a1623f87bc -r bc78c038fddf src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h	Mon Oct 21 18:20:32 2013 +0800
+++ b/src/http/ngx_http_core_module.h	Thu Oct 24 18:50:37 2013 -0700
@@ -572,11 +572,13 @@
         r->headers_out.location = NULL;                                       \
     }
 
-#define ngx_http_clear_etag(r)                                                \
+#define ngx_http_clear_strict_etag(r)                                         \
                                                                               \
     if (r->headers_out.etag) {                                                \
-        r->headers_out.etag->hash = 0;                                        \
-        r->headers_out.etag = NULL;                                           \
+        if (! ngx_strncmp(r->headers_out.etag->value.data, "W/", 2)) {        \
+            r->headers_out.etag->hash = 0;                                    \
+            r->headers_out.etag = NULL;                                       \
+        }                                                                     \
     }
 
 
diff -r e6a1623f87bc -r bc78c038fddf src/http/ngx_http_special_response.c
--- a/src/http/ngx_http_special_response.c	Mon Oct 21 18:20:32 2013 +0800
+++ b/src/http/ngx_http_special_response.c	Thu Oct 24 18:50:37 2013 -0700
@@ -657,7 +657,7 @@
 
     ngx_http_clear_accept_ranges(r);
     ngx_http_clear_last_modified(r);
-    ngx_http_clear_etag(r);
+    ngx_http_clear_strict_etag(r);
 
     rc = ngx_http_send_header(r);
 
@@ -756,7 +756,7 @@
 
     ngx_http_clear_accept_ranges(r);
     ngx_http_clear_last_modified(r);
-    ngx_http_clear_etag(r);
+    ngx_http_clear_strict_etag(r);
 
     rc = ngx_http_send_header(r);
 
