ZF-3076: Zend_Cache_Frontend_Page empty cache on non 200 HTTP status

Description

I have come across a serious problem with using Frontent_Page when implementing additional HTTP status.

This includes the problem in issue #ZF-2841, but has more serious implications.

The frontend cache's a page no matter what HTTP status was sent in the response, and then serves it as though it was a HTTP/1.x 200 OK.

I have implemented correct Last-Modified/If-Modified-Since behaviour in my website, and so it sends a HTTP/1.1 304 Not Modified when the browser has an up to date cache.

The problem is, when I change the http status (php function header()), I exit the request, as is meant to be done. The ob_start callback then caches the blank response. Once this is in the cache, it will be served as a blank page on subsiquent requests.

I would assume this would happen on any other HTTP status which involves any other way of sending alternative content/behaviour (e.g. 206, 301, 307 even 404s?). The correct behaviour would be to only cache if the HTTP status was 200 (or have some alternative storage for redirects).

I have tried looking for a php solution that would return the sent status, but not found any. Sadly headers_list does not include this. So I think the only way to fix this is to modify the php binary itself to include something that does this. Alternatively any cache/redirect/etc behaviour would need to be registered before hand by a Zend php class, but this wouldn't be ideal.

Comments

Please evaluate and categorize/assign as necessary.

I understand your problem. But there is no easy solution for this.

I keep this issue open as a reminder

We will work soon on the "headers" part of Frontend_Page.

I think the simplest tidy solution at the moment would be to add a "cancel" method to the class, so in the very least, anyone who alters headers and exits can stop the page from being cached. e.g.

header('Location: /newpage.html'); $cache->cancel(); exit;

hum... good idea !

I just commited in SVN trunk your cancel() method

can you give it a try ?

thanks

Updating for the 1.6.0 release.

If anyone stumbles on this: The current option to solve the problem described here is memorize_headers.

memorize_headers Array array(): an array of strings corresponding to some HTTP headers name. Listed headers will be stored with cache datas and "replayed" when the cache is hit

See http://framework.zend.com/manual/en/…

I'm not sure how you mean memorize_headers should be used for it. That is used to tell the cache what response headers to cache.

The response headers themselves are retrievable after being sent. Its just the HTTP status isn't, and a redirect or error can't be recognised to stop the cache.

The cancel method Fabien implemented, that's documented further down that page, is the only realistic workaround without a PHP binary fix.

Sorry, should have made myself clearer. I was responding to your comment about canceling when changing the Location header:

header('Location: /newpage.html'); $cache->cancel(); exit;

In this case, the redirect will work if you simply add Location to memorize_headers.

Unfortunately this does not help with Status no being replayed and the page cache will still return 200 OK when loading the page from cache instead of any 301 or 302 you may be setting with header or $response->setRawHeader...

The jist of it for me at least is: HTTP Error codes -> cancel cache using the cancel() method. HTTP Redirect codes: you can still cache the pages by adding 'Location' to memorize_headers, while the code will not be replayed, the Location header will be.

Why not just memorize the response codes too?