61

What is the difference between Expires: 0 and Expires: -1 in the HTTP response header? RFC 2616 defines invalid date formats, especially including the value "0" as already expired. However, some servers (e.g. www.google.de) reply with Expires: -1.

Is there an advantage over using -1 over 0 or is this even required for some broken HTTP clients?

Community
  • 1
  • 1
scai
  • 20,297
  • 4
  • 56
  • 72
  • 5
    It doesn't define `"0"` as "already expired" - it defines "invalid date formats", *including* `"0"`, as "already expired" – Damien_The_Unbeliever Jul 06 '12 at 07:30
  • That's correct, thanks for this hint. But it seems to me like "0" should be preferred when specifying an "invalid date format". – scai Jul 06 '12 at 07:32
  • 2
    No, the preference (expressed in the next paragraph) is to use a valid date format, containing the same value as the `Date` header, to indicate already expired. – Damien_The_Unbeliever Jul 06 '12 at 07:34
  • 1
    Thanks again. After trying various servers I couldn't find any one that uses the same value in the _Date_ and _Expires_ field, so I guess this might be some compatibility thing or simplification or just lack of knowledge. – scai Jul 06 '12 at 07:47
  • 4
    Question Still Needs an Answer: In 2018, when all the browsers against my site are evergreen, is it better to use 0 or -1. It is possible that I am encountering corporate caching proxy servers that should prefer 0 or “-1” to accomplish no caching – but I do not have good guidance on this. The spec would imply that 0 is better than -1. (so why is -1 used everywhere? (old ie detail that may not be relevant anymore)) – Sql Surfer Feb 15 '18 at 15:58

3 Answers3

34

The problem is in how invalid Expires header processed by Internet Explorer (especially older versions). IE uses Trident layout engine and WinINET API to process HTTP requests. As you may know Expires could be specified in HTTP header

Expires: 0

or in meta tag

<meta http-equiv="Expires" content="0">

In second case, Expires became part of the response content (not header content), so it will be processed by Trident and then propagated to WinINET:

If WinINET downloads a response with an invalid Expires header (e.g. one that doesn’t contain a valid HTTPDATE value) and no other caching directives, it will mark the document as having expired one hour ago. Trident, however, has no such logic. If you specify an invalid time, Trident grabs the current timestamp and uses that as the expiration. Trident will also use the current timestamp if it encounters the Pragma: no-cache directive. If the user tries to re-navigate to the current document during same exact second that the HTTP/404 was processed, the incorrectly-updated expiration of the existing cache entry will result in it being treated as fresh for that request. If the user hit the Refresh button or F5, the cache would be bypassed and the 404 page would be shown.

In other words Expires: 0 not always leads to immediate resource expiration, therefore should be avoided and Expires: [some valid date in the past] should be used instead.

Mikko Rantalainen
  • 14,132
  • 10
  • 74
  • 112
Pavel Podlipensky
  • 8,201
  • 5
  • 42
  • 53
  • 1
    That's the "some broken HTTP client" answer I was waiting for and explains the reason for "Expires: -1", thanks! :) – scai Jul 08 '12 at 19:55
  • 13
    3 upvotes? Did anybody even read the answer? According to the article, there is *no difference* between `Expires:-1` and `Expires:0`. – user123444555621 Dec 18 '12 at 05:31
  • 4
    That's correct. The article only explains an incorrectly handled *Expires=0* in the HTML meta element. Not a single word about *Expires=-1* or other incorrectly handled Expires values in the HTTP header. – scai Feb 25 '13 at 09:13
  • "RFC Note: Never use Expires = 0 to prevent caching." ... however, IE seems to regard this as "never expires" on forms, always displaying the old page after posting new information. IE is safer to use -1. Some browsers refuse -1. So it depends on your traffic and form usage. Lots of IE and forms, use -1 – ppostma1 Jan 15 '14 at 22:03
  • Thank you. But these tags didn't help me for "go back" and "go forward" in Chrome Version 63.0.3239.132: How can I disable cache for "go back" and "go forward"? – RoutesMaps.com Jan 18 '18 at 16:49
  • I checked in Eclipse debugger that servlets do not handle requests from IE 11, Chrome 63. – RoutesMaps.com Jan 18 '18 at 18:34
13

Expires: -1 The Expires header specifies when the content should be considered to be out of date. The value -1 indicates that the content expires immediately and would have to be re-requested before being displayed again. http://www.httpwatch.com/httpgallery/headers/

max-age=0 simply tells caches (and user agents) the response is stale from the get-go and so they SHOULD revalidate the response (eg. with the If-Not-Modified header) before using a cached copy, whereas, no-cache tells them they MUST revalidate before using a cached copy.

for more info look into http://www.w3.org/Protocols/HTTP/1.1/rfc2616.pdf

Arjun Suthar
  • 147
  • 1
  • 2
  • 5
    Thanks, but my question has been specifically about the difference between `Expires: 0` and `Expires: -1`. – scai Mar 10 '15 at 08:23
  • +1 Though not really an answer to the question, but it's relevant to the topic. Seems to me if you are trying to to add expires: -1 or 0 you will likely be using the max-age=0 as well. Probably should have been a comment rather than an answer. – Jeremy A. West Apr 20 '16 at 15:24
11

Using "-1" is invalid, and would be treated the same as "0". It should not trigger a reload at all.

Be careful: in some browsers, it may give 1 hour extra or use default expire time for caching.

1- So better to give it a correct old date like:

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />

For formal work, I advise to give the current date time to meta Expires instead of using Old fixed date ( that will make search engines like google mark your site as old and not be shown on toppers)

2- if your Backend is PHP you can deal with it like:

<meta http-equiv="Expires" content="<?php echo gmdate('D, d M Y H:i:s', time()-3600) . ' GMT' ?>" />

PS: I give one hour before just for in case.

Vinay Prajapati
  • 7,199
  • 9
  • 45
  • 86
Mohamed Abulnasr
  • 589
  • 7
  • 18