21

This is a follow up question to Using 301/303/307 redirects for dynamic short urls, where I try to determine the best method for implementing short url redirection when the destination url will change on a frequent basis.

While it seems that 301 and 307 redirects both perform the same way, the issue that concerns me is 301 redirect caching (as documented here)- is the best way to avoid this to use 307 redirects instead (I'm assuming 307 redirects will never cache?), or to explicitly send a no-cache header ("Cache-Control: no-cache, must-revalidate")?

Community
  • 1
  • 1
Yarin
  • 173,523
  • 149
  • 402
  • 512

2 Answers2

29

Don't try to avoid 301 caching. If you don't want any user agent to cache your redirect, then simply don't use a 301 redirect. In other words, 301 caching is here to stay, and semantically, it's a permanent redirect, so if you're planning to change the destination URL, 301 is not the right status code to use. On the other hand, 307 responses are not cached by default.

Mauricio Scheffer
  • 98,863
  • 23
  • 192
  • 275
  • 5
    Your interpretation violates the HTTP specification. Clients must follow `Cache-Control` when it's present on a 301. – Gili Nov 12 '13 at 19:11
  • @Gili yes, clients must honor Cache-Control, but a 301 is still *permanent*, and shouldn't be used if the redirect is not intended to be permanent. Because it's permanent, it's cachable by default as defined in https://tools.ietf.org/html/rfc2616#section-10.3.2 – Mauricio Scheffer Nov 12 '13 at 19:17
  • 301 does not have to be *permanent* (that's just the default caching rule). According to http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-24#section-6.4.2 `A 301 response is cacheable unless otherwise indicated by [...] explicit cache controls` where `explicit cache controls` means `Cache-Control` and related headers. – Gili Nov 12 '13 at 19:25
  • 1
    The RFC says "The 301 (Moved Permanently) status code indicates that the target resource has been assigned a new permanent URI", so yes, that means it's permanent. Of course you can technically use it for other purposes, but then you're misusing HTTP semantics. – Mauricio Scheffer Nov 12 '13 at 19:45
  • 10
    You're reading too much into the name. Nothing is forever. Domain names get sold. Companies go bankrupt. There are even technical limitations preventing this: http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-24#page-28 `[...] extremely large values have been demonstrated to cause problems [...]` In conclusion: `Forever` just means `until the resource is deleted, or a reasonably long time.` – Gili Nov 13 '13 at 01:38
  • 5
    There is a final point you're missing: `301` is the only reasonable response for URI canonicalization. Codes `303` and `307` require clients to repeat requests on the original URI (defeating the point of URI canonicalization): http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-24#section-6.4.7 `Since the redirection can change over time, the client ought to continue using the original effective request URI for future requests.` URI canonicalization means clients should be able to use the canonical URI instead of the alias that redirected to them. Codes `303` and `307` prevent this. – Gili Nov 13 '13 at 01:46
  • 3
    You're right about one thing though: OP wants to redirect without caching. In such a case, `307` is a better solution. I'm just saying that `301` with `Cache-Control` headers is perfectly reasonable and should not be ruled out for other uses. – Gili Nov 13 '13 at 01:50
13

In situations where you want the behaviour that a 301 redirect brings, like the updating of browser bookmarks and the change of URL in google bot, but at the same time want to track the redirects or perform some other kind of functionality you can always add the cache control headers to "no cache"

HTTP/1.0 301 Moved Permanently
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Location: http://example.com

In php it looks like this:

header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Location:'.$url, true, 301);

Related: https://stackoverflow.com/a/19003320/175071

Community
  • 1
  • 1
Timo Huovinen
  • 53,325
  • 33
  • 152
  • 143