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 =

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.


More information about the varnish-dev mailing list