WordPress.org

Make WordPress Core

Opened 7 years ago

Closed 7 years ago

#22258 closed defect (bug) (fixed)

nocache_headers fail to prevent aggressive caching in Chrome

Reported by: andy Owned by: nacin
Milestone: 3.5 Priority: normal
Severity: normal Version: 3.5
Component: General Keywords: has-patch commit
Focuses: Cc:
PR Number:

Description

In Chrome 22, a response with a valid Last-Modified header will be cached despite Cache-Control and Expires headers. So even though the user is logged in, the resource is cached and the browser sends If-Modified-Since with subsequent requests. This can result in a strange, partially-logged out experience with batcache under certain conditions.

In wp_get_nocache_headers(), the Last-Modified header is set to the current time. Setting its value to the empty string resolves the issue.

I will post two patches: one which only empties the Last-Modified header in the array, another which also removes the header when the header_remove() function is defined (PHP >= 5.3).

Attachments (4)

22258.1.diff (498 bytes) - added by andy 7 years ago.
Empty Last-Modified
22258.2.diff (2.0 KB) - added by andy 7 years ago.
Empty Last-Modified and remove header if PHP >= 5.3
22258.3.diff (1.2 KB) - added by nacin 7 years ago.
22258.4.diff (1.2 KB) - added by nacin 7 years ago.

Download all attachments as: .zip

Change History (20)

@andy
7 years ago

Empty Last-Modified

@andy
7 years ago

Empty Last-Modified and remove header if PHP >= 5.3

#1 @barry
7 years ago

The same thing happens in Safari 6.0.1 as well.

#3 @nacin
7 years ago

  • Keywords commit added
  • Milestone changed from Awaiting Review to 3.5

Looks good. Goes nicely with #21745.

#4 follow-up: @nacin
7 years ago

Because there are filters in both wp_get_nocache_headers() and WP::send_headers(), here is an alternative patch.

@nacin
7 years ago

#5 in reply to: ↑ 4 @andy
7 years ago

Replying to nacin:

Because there are filters in both wp_get_nocache_headers() and WP::send_headers(), here is an alternative patch.

I endorse this patch.

@nacin
7 years ago

#6 @nacin
7 years ago

Only side effect of 22258.3.diff is it could remove a valid Last-Modified header that is not set by WP or via the wp_headers filter. I don't think this is an issue, but in the interest of CYA, two possibilities: the extra send_headers() logic andy has, or 22258.4.diff.

#7 @nacin
7 years ago

RFC2616 doesn't say much about this, but some reading: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-13#page-10. If the Date and Last-Modified headers are within 60 seconds (and they would be here, barring a server misconfiguration), it is considered a weak validator, because of potential timing inconsistencies; they are also considered weak for being only accurate to the second.

#8 @nacin
7 years ago

  • Owner set to nacin
  • Resolution set to fixed
  • Status changed from new to closed

In [22283]:

Do not issue a Last-Modified header when issuing no-cache headers to avoid aggressive (webkit) caching. Serve a blank header when header_remove() is not available (PHP < 5.3). props andy. fixes #22258.

#9 follow-up: @ryan
7 years ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

Do we want to silence header_remove() like we do header() to avoid "Cannot modify header information - headers already sent by..." messages? These are popping up all over the unit tests.

#10 @andy
7 years ago

Good catch, but the @-bandage wastes more dev time than a clean fix would. I would rather see core functions with header() calls do something smart like check headers_sent() and trigger_error().

#11 @nacin
7 years ago

Would probably be easiest if we just checked headers_sent() at the start of nocache_headers(), and in WP::send_headers(). There's no reason to error-suppress header() a half-dozen times when we can bypass it all together.

#12 @nacin
7 years ago

Though, @ isn't as bad, because if someone is using xdebug.scream or a custom error handler (including the Debug Bar), it doesn't get masked in the way headers_sent() would. At least it is consistent with our use of @header(), and we can possibly make changes later.

#13 in reply to: ↑ 9 @sirzooro
7 years ago

  • Cc sirzooro added

Replying to ryan:

Do we want to silence header_remove() like we do header() to avoid "Cannot modify header information - headers already sent by..." messages? These are popping up all over the unit tests.

Maybe it is good time to reconsider #21282 ?

#14 @nacin
7 years ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In [22303]:

Avoid 'headers already sent' messages for header_remove() the same way we currently do with header(). props ryan. fixes #22258.

#15 @slene
7 years ago

  • Cc slene added
  • Keywords needs-patch added; has-patch removed
  • Resolution fixed deleted
  • Status changed from closed to reopened

In php5.2 the Last-Modified header always blank !!!

A response with a blank Last-Modified header will be set to "Thu, 01 Jan 1970 00:00:00 GMT" in some server. The browser will be always send a If-Modified-Since header "Thu, 01 Jan 1970 00:00:00 GMT". and the server response a 304 status code. Make the browser can not refresh cache.

sorry my bad english...

#16 @SergeyBiryukov
7 years ago

  • Keywords has-patch added; needs-patch removed
  • Resolution set to fixed
  • Status changed from reopened to closed

This ticket was closed on a completed milestone. If you believe there's a problem, please open a new one. That sounds like server misconfiguration though.

Note: See TracTickets for help on using tickets.