Hiding 302 replies from clients
T. Pascal
t_pascal at zennet.com
Wed Aug 11 20:26:35 CEST 2010
> Suppose the back-end replies with a 302 return code ("Found" or "Moved
> temporarily"). From a quick test, it seems that Varnish will relay this 302
> reply back to the client. The client will extract the new URL from the
> "Location" header field and make a second request.
>
This works: for us (we normalise the + and space to %20; you can use
any other normalisation you need to ensure the hash-key is the same):
vcl_fetch() {
if ((beresp.status == 301) || (beresp.status == 302)) {
# Try again at the new location (normalise + and space to %20)
# and strip the leading http://host/ part
set req.url =
regsub(req.url,".*",regsuball(regsub(beresp.http.Location,"^http://[^/]+(.*)","\1"),"[
+]","%2520"));
restart;
}
}
You also have to use some URL parsing to map to different backends which we use.
> [aside: from a quick test, it seems that varnish always caches the 302 reply
> from the back-end. It will give the same reply if a client asks for the same
> URL, even when the back-end reply omits any "Cache-Control" or "Expires"
> header. If this is so then it's a bug.]
>
I'm not an expert on the RFC by any means, but it is permissible to
cache 302 (temporary) for a reasonable timeframe and 301 for a long
timeframe. I have verified that if you specifically use no-cache in
your headers that varnish will not cache the 302. Not sure about 301;
I think it is semantically correct to ignore cache headers and keep a
301 "indefinitely" (otherwise don't use a 301!).
> In case you're wondering, here's why... Simplifying the setup somewhat,
> consider a distributed http service where a central server that knows about
> all the files but hosts none of the data. When a client requests a file, the
> central server redirects the client to whichever server is currently hosting
> that file by replying with a 302 reply. The client can read that file from the
> hosting server with the URL in the "Location" header.
>
Caching the 302 is fast, and allowing the client to follow to the
Location:, and then caching THAT response from the other backend is
perfectly fast and not really a reason to hide the 302. In fact, if
your client supports following the Location header (which it should) I
don't recommend tampering with it at all. The only reason I
implemented the above solution is because our "client" is broken and
couldn't follow 301/302 for us.
-T.
More information about the varnish-dev
mailing list