ZF-2841: Zend_Cache_Frontend_Page and Redirector : add header redirect saving support to Zend_Cache_Frontend_Page

Description

snapshot : 8205

I m using Zend_Cache_Frontend_Page and Redirector (action helper).

the first time a page is generated, the redirection (gotoRouteAndExit) goes fine, but when the page is called from the cache, "of course" the header 'redirect' is not present...

It will be interesting to add more header support to Zend_Cache_Frontend_Page and of course redirection headers.

best regards

Comments

I agree with you

We will work on this part soon

Other important headers (Expires, for example) are also not preserved. This effectively prevents you from caching a far-future expiring document (YSlow recommendation #3).

Is there any good reason not to preserve every response header for cached pages (possibly by default)? I cannot think of a situation where a cached copy of a document would be expected to have different headers than the original.

I just commited into SVN trunk a new option in Frontend_Page backend :


     * ====> (array) memorize_headers :
     * - 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

Can you try it ?

This patch fixes two issues in rev 9496:

  1. correctly spell "strtolower"
  2. don't truncate header contents that contains a colon

your patch is added to my source tree (thanks)

SVN is down but I will commit it soon

fixed in SVN trunk

works for me, thanks. (i didn't test it for "redirect" which is what this issue was primarily meant to address, so maybe the original author could verify that this works for him as well.)

might still be nice to have a "standard" set of preserved headers, or at least a well-documented set of headers that are generally desirable to preserve. cache troubleshooting is bad enough without having to locate issues related to unexpected/varying HTTP response headers...

hi,

Great job ;p

just one thing : the way it's implemented (split header on ':') makes impossible to deal 404 header (in ex) ...

best regard

re-hi,

for the default set of header, maybe a "keep all headers" option would do it...

can you provide an example ?

{{



to send a 404 header, you don't use this :

header("Status: 404 Not Found"); 

?

{{

hi,

a quick search on g***** says :

header("HTTP/1.0 404 Not Found");

and ...

header("Status: 404 Not Found");

the 2nd form seams to have some compatibility issue

http://bugs.php.net/bug.php?id=32122

hi,

sorry for me it does not work.

I m in MVC mode and the headers are never stored !

[code] public function _flush($data) { if ($this->_cancel) { return $data; } $contentType = null; $storedHeaders = array(); header('Pragma: public'); if (headers_sent()) { //never here because the headers are not sent.... $buffer.='sent'; $headersList = headers_list(); foreach($this->_specificOptions['memorize_headers'] as $key=>$headerName) { $buffer.='m='.$headerName.';'; foreach ($headersList as $headerSent) { $buffer.=$headerSent.'-';

                $tmp = split(':', $headerSent);
                $headerSentName = trim(array_shift($tmp));
                if (strolower($headerName) == strtolower($headerSentName)) {
                    $headerSentValue = trim(implode(':', $tmp));
                    $storedHeaders[] = array($headerSentName, $headerSentValue);
                }

            }
        }
    }
    $array = array(
        'data' => $data,
        'headers' => $storedHeaders
    );
    $this->save($array);
    return $data;
}

[/code]

and if I can put an advise : looping on the headers to store and over looping on the header sent is a lack of time. if you want to store 10 headers and if they are 20 headers sent you loop 200 times... it's 180 too many.

1st step : create a temporary array of wanted header in strtolower format

2nd step : loop over header list (without checking if it's sent or not) if(eregi('^([^:])[:]', $headerLine, $regs) ) $headerSentName=strtolower($regs[1]); else { /* special cases */ } and check with in_array in the wanted header ()...

and storing the whole header is easyer than all the split stuff.... (and maybe there can be multiple occurencies one special header)

best regard

Regarding HTTP Status header: the problem applies only to PHP3 (at least according to the link you provided). Clearly PHP3 is not supported by Zend Framework and we should therefore prefer "Status: 404 Not Found" to the alternative.

Regarding your MVC example not working: it's a chicken and egg problem. You have to manually construct the list of headers you want to preserve. I too originally thought it would be nice to have the ability to automatically store all of the headers using headers_list(), but after giving it some thought I don't know if it's a good idea. There are some headers that should usually not be stored, such as Date, Server, X-Powered-By, and Set-Cookie, to name a few.

Regarding inefficiency of the nested loop in the implementation: you're absolutely correct. One way to improve it without using eregi() is to first iterate over _specificOptions['memorize_headers'] to force keys to lowercase, then iterate over headersList, and for each header do the split + strtolower() and use array_key_exists() to check for the key in _specificOptions['memorize_headers']. I don't think there is any way to send multiple occurrences of a header, as PHP is advertised to replace rather than append. I would make and post a patch but svn is down and I don't have up-to-date sources...

I ve found multiple occurrencies of Cache-Control: ...

I think it's not the goal of the cache layer to add header rules. The cache layer must just mimic the page engine...

here is what works with me.... (9566 on snapshot).

it's ereg free and uses explode in place of split... and it stores the whole header ;p

maybe it could be improved with an ereg pattern filter in place of just a fixed string match...

Updating for the 1.6.0 release.