You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bugs@httpd.apache.org by bu...@apache.org on 2020/09/07 15:22:06 UTC

[Bug 61820] 304 headers stripped

https://bz.apache.org/bugzilla/show_bug.cgi?id=61820

--- Comment #23 from Matt McCutchen <ma...@mattmccutchen.net> ---
Thanks to everyone who worked or is working on this issue!  While we wait for
the fix to be committed and deployed to our web hosts (which I'm guessing may
take years), here's a workaround I plan to use on my site:

For each request, compute a "salt" string that uniquely identifies the relevant
response header values, and then emulate a resource whose ETag incorporates the
salt.  Thus, if a request returns a salted ETag that is found in the client's
cache, then the response headers in the cache are guaranteed to equal those
that would have appeared in the actual response if Apache didn't strip them. 
Since a last-modified time cannot accommodate salt, the If-Modified-Since
request header must be dropped so that a 304 is not returned on that basis.

In general, the response headers and thus the salt could depend on both the
server configuration and the request headers.  In most scenarios, it's probably
easiest to represent the server configuration by an integer that is manually
incremented for each relevant change.  Request headers can just be concatenated
into the salt with any problematic characters suitably encoded.

Of course, we must ensure the client sends the request to the server in the
first place rather than fulfilling it from cache.  This is independent of the
current issue but probably worth reminding people about.  For a dependency on a
request header, we just merge its name into the Vary response header.  For a
change in server configuration, the best we can do is set the Cache-Control
max-age to ensure clients eventually find out about the change.

Here's a code example for a .htaccess file where, if the Origin request header
specifies an allowed origin, we want to set an equal
Access-Control-Allow-Origin response header.  The server configuration revision
is 42; we would increment the number if we changed the logic for generating
response headers.  I'm assuming no browser sends an Origin header with nasty
characters; this might need more research.  Please let me know if anything is
wrong with this example!

~~~~~~~~
SetEnv HEADER_CONFIG_REV 42
RewriteRule ^ - [E=ETAG_SALT:%{ENV:HEADER_CONFIG_REV}-%{HTTP:Origin}]
Header merge Vary Origin
Header set Cache-Control max-age=1200

# Our goal is to strip the salt from the If-None-Match and If-Match headers if
# it equals the current salt.  However, %{ETAG_SALT}e expansion in the regular
# expression is not supported, so we use the following hack: append the current
# salt to all ETags, and then if an ETag ends in two equal salts (as determined
# by a regular expression with a \1 backreference), strip both of them.  ETags
# that did not originally end with the current salt will be left with at least
# one salt and won't be able to match the real ETag, so their presence does not
# matter.
RequestHeader edit* If-None-Match "([^\ ])\"" "$1+%{ETAG_SALT}e\""
RequestHeader edit* If-None-Match "(\+[^+\" ]*)\1\"" "\""
RequestHeader edit* If-Match "([^\ ])\"" "$1+%{ETAG_SALT}e\""
RequestHeader edit* If-Match "(\+[^+\" ]*)\1\"" "\""
RequestHeader unset If-Modified-Since

# Always add the salt to the ETag response header.
Header edit ETag "\"$" "+%{ETAG_SALT}e\""

RewriteCond %{HTTP:Origin} ^https://(.+\.)?example\.com$
RewriteRule ^ - [E=ACAO:%{HTTP:Origin}]
Header set Access-Control-Allow-Origin %{ACAO}e env=ACAO
~~~~~~~~

When calling a CGI, some of this processing could probably be done in the CGI,
but I haven't tested that.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org