Add Support for Weak ETags
Maxim Dounin
mdounin at mdounin.ru
Tue Nov 12 16:46:27 UTC 2013
Hello!
On Mon, Nov 04, 2013 at 05:14:12PM -0800, Aaron Peschel wrote:
> I reduced the scope of the changes to just the gzip and gunzip modules.
I don't think that limiting the scope to gzip and gunzip is
correct either. From cache validation point of view, weak etags
are mostly identical to Last-Modified, and removing etags
completely should mostly follow ngx_http_clear_last_modified().
Here is a patch, untested:
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1384274233 -14400
# Tue Nov 12 20:37:13 2013 +0400
# Node ID 2c4e71a1c9a3467ba53115b693549c41f248164e
# Parent f3c95d2d7d5e2d69c4b4fd99421b3193d43adab0
Entity tags: only clear strict etags if weak ones are ok.
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c
--- a/src/http/modules/ngx_http_addition_filter_module.c
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -121,7 +121,7 @@ ngx_http_addition_header_filter(ngx_http
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 --git a/src/http/modules/ngx_http_gunzip_filter_module.c b/src/http/modules/ngx_http_gunzip_filter_module.c
--- a/src/http/modules/ngx_http_gunzip_filter_module.c
+++ b/src/http/modules/ngx_http_gunzip_filter_module.c
@@ -165,7 +165,7 @@ ngx_http_gunzip_header_filter(ngx_http_r
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 --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -306,7 +306,7 @@ ngx_http_gzip_header_filter(ngx_http_req
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 --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -368,10 +368,13 @@ ngx_http_ssi_header_filter(ngx_http_requ
if (r == r->main) {
ngx_http_clear_content_length(r);
ngx_http_clear_accept_ranges(r);
- ngx_http_clear_etag(r);
if (!slcf->last_modified) {
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
+
+ } else {
+ ngx_http_clear_strict_etag(r);
}
}
diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c
--- a/src/http/modules/ngx_http_sub_filter_module.c
+++ b/src/http/modules/ngx_http_sub_filter_module.c
@@ -175,10 +175,13 @@ ngx_http_sub_header_filter(ngx_http_requ
if (r == r->main) {
ngx_http_clear_content_length(r);
- ngx_http_clear_etag(r);
if (!slcf->last_modified) {
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
+
+ } else {
+ ngx_http_clear_strict_etag(r);
}
}
diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c
--- a/src/http/modules/ngx_http_xslt_filter_module.c
+++ b/src/http/modules/ngx_http_xslt_filter_module.c
@@ -337,12 +337,14 @@ ngx_http_xslt_send(ngx_http_request_t *r
r->headers_out.content_length = NULL;
}
- ngx_http_clear_etag(r);
-
conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module);
if (!conf->last_modified) {
ngx_http_clear_last_modified(r);
+ ngx_http_clear_etag(r);
+
+ } else {
+ ngx_http_clear_strict_etag(r);
}
}
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -579,5 +579,16 @@ extern ngx_str_t ngx_http_core_get_meth
r->headers_out.etag = NULL; \
}
+#define ngx_http_clear_strict_etag(r) \
+ \
+ if (r->headers_out.etag \
+ && (r->headers_out.etag->value.len < 2 \
+ || r->headers_out.etag->value.data[0] != 'W' \
+ || r->headers_out.etag->value.data[1] != '/')) \
+ { \
+ r->headers_out.etag->hash = 0; \
+ r->headers_out.etag = NULL; \
+ }
+
#endif /* _NGX_HTTP_CORE_H_INCLUDED_ */
But I don't really sure we need preserving weak etags aproach. It
requires a backend to know that weak etags can be used, while
strict ones can't. This is basically what we already have - but
with Last-Modified instead of etags.
It could be done better - strict etags can be downgraded to weak
ones if we change entity representation (but not semantics). This
way it will do its best while handling all possible responses.
This will require much more changes though.
> # HG changeset patch
> # User Aaron Peschel <aaron.peschel at gmail.com>
> # Date 1383613159 28800
> # Mon Nov 04 16:59:19 2013 -0800
> # Node ID c0a50e6aac95feac6393dd6bff0b30bd1a05ef9e
> # 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.
Just a side note: referring to Mercurial changesets with revision
numbers can be ambigous, as different clones may have different
revision numbers. It's a good idea to referer to a revision hash
or a revision id and hash as shown by hg log, e.g. 4746:4a18bf1833a9.
--
Maxim Dounin
http://nginx.org/en/donation.html
More information about the nginx-devel
mailing list