diff options
author | Robert Newson <rnewson@apache.org> | 2019-03-06 14:58:23 +0000 |
---|---|---|
committer | Robert Newson <rnewson@apache.org> | 2019-03-06 15:08:08 +0000 |
commit | c151a321da0df18fb563b9cd09ba64e56e540e38 (patch) | |
tree | 2d77128c497a6079ddec33b6cc4d7c50f665ebbf | |
parent | aee2fd9859c14aed1cb28f458a846064c58cf782 (diff) | |
download | couchdb-c151a321da0df18fb563b9cd09ba64e56e540e38.tar.gz |
Ignore weak ETag part
Some load balancer configurations (HAproxy with compression enabled is
the motivating example) will add W/ to our response ETags if they
modify the response before sending it to the client.
as per rfc7232 section 3.2;
"A recipient MUST use the weak comparison function when comparing
entity-tags for If-None-Match (Section 2.3.2), since weak entity-tags
can be used for cache validation even if there have been changes to
the representation data."
This change improves our ETag checking toward RFC compliance.
-rw-r--r-- | src/chttpd/src/chttpd.erl | 8 | ||||
-rw-r--r-- | test/javascript/tests/etags_head.js | 4 |
2 files changed, 11 insertions, 1 deletions
diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl index ac371a2e5..1e1d638be 100644 --- a/src/chttpd/src/chttpd.erl +++ b/src/chttpd/src/chttpd.erl @@ -693,10 +693,16 @@ etag_match(Req, CurrentEtag) when is_binary(CurrentEtag) -> etag_match(Req, binary_to_list(CurrentEtag)); etag_match(Req, CurrentEtag) -> - EtagsToMatch = string:tokens( + EtagsToMatch0 = string:tokens( chttpd:header_value(Req, "If-None-Match", ""), ", "), + EtagsToMatch = lists:map(fun strip_weak_prefix/1, EtagsToMatch0), lists:member(CurrentEtag, EtagsToMatch). +strip_weak_prefix([$W, $/ | Etag]) -> + Etag; +strip_weak_prefix(Etag) -> + Etag. + etag_respond(Req, CurrentEtag, RespFun) -> case etag_match(Req, CurrentEtag) of true -> diff --git a/test/javascript/tests/etags_head.js b/test/javascript/tests/etags_head.js index ab5476921..9faca4af6 100644 --- a/test/javascript/tests/etags_head.js +++ b/test/javascript/tests/etags_head.js @@ -63,6 +63,10 @@ couchTests.etags_head = function(debug) { headers: {"if-none-match": etag} }); T(xhr.status == 304); + xhr = CouchDB.request("GET", "/" + db_name + "/1", { + headers: {"if-none-match": "W/" + etag} + }); + T(xhr.status == 304); // fail to delete a doc xhr = CouchDB.request("DELETE", "/" + db_name + "/1", { |