Caching at HTTP-Level

Hello, there is what I think a big bug in your implementation because it wont allow to cache pages in deed, you are setting Cache-Control in prefiltering, but it get overwrited to default by the call to function "return ob_get_clean();" in line 128 of CBaseController.php.
It took me some time to dig on this.
To fix it you only has to call to sendCacheControlHeader function on postFilter() overwrited function in your CHttpCachedFilter class.
I hope this helps.
regards,
alex

Well, with this fix I'm having some problems rendering some pages like "contact" or "login". It throws the typical error message:Cannot modify header information - headers already sent by (output started at E:\EasyPHP\www\yii\framework\web\CController.php:794)

Anyway, I couldnt get a "cached" page yet. I try it turning off my connection and refreshing but no way!!
Does some body actually got this http cache really working?

aleksdj, on 01 September 2012 - 10:35 PM, said:

Hello, there is what I think a big bug in your implementation because it wont allow to cache pages in deed, you are setting Cache-Control in prefiltering, but it get overwrited to default by the call to function "return ob_get_clean();" in line 128 of CBaseController.php.
It took me some time to dig on this.
To fix it you only has to call to sendCacheControlHeader function on postFilter() overwrited function in your CHttpCachedFilter class.
I hope this helps.
regards,
alex

Ok I've got the problem and bug, let me explain and give you a solution:

The problem:
Whenever you use the "User session" for example in the scafolded default Top Menu (when it uses Yii::app()->user) the internal code (at line 115 of CHttpSession for example, and maybe in other locations) call the php function session_start(), and according to PHP manual, "This function sends out several HTTP headers depending on the configuration", among that it clears the "Cache control" header, so the header of your HTTP class filter gets overwrited and doesn't work. In the same manual it says you can customize or parametrice this cache control header if you call to function cache_session_limiter in every request before start the session.

Well, that fix won't work if there has been no session started. And I need to figure out a way to incorporate this change without the introduction of BC-breaking behaviours. So let's just say I'll need a bit.

programmer /ˈprəʊgramə/, noun: a device that converts ►coffee into ►code

I've been trying to use it, and probably also because of my little knowledge on a couple of subjects, I'm having an hard time to understand how to better use the etagSeed, as there's little if no evidence on how to use it correctly on this website.

Currently I have no problem in setting it to any string, but anything more complex (for instance the name of the action using $this->action->id) will throw an error as the filter is evaluated at the very beginning.
Is it something I should be worried about or that's simply enough to have anything in there? (i.e. are pages served with the same etag OK or is it something not exactly correct?)

Second question: on one of my actions I can't get the Cache-Control to be set. The browser request contains a Cache-Control: max-age=0; (for reasons to me unknown) and this *seems* to cause Cache-Control to be returned with value: no-store, no-cache, must-revalidate, post-check=0, pre-check=0. I still don't know who's outputting it (default apache behaviour?). I wonder if this is the same problem reported by Aleksdj.

Currently I have no problem in setting it to any string, but anything more complex (for instance the name of the action using $this->action->id) will throw an error as the filter is evaluated at the very beginning.
Is it something I should be worried about or that's simply enough to have anything in there? (i.e. are pages served with the same etag OK or is it something not exactly correct?)

I take it you are trying to set CHttpCacheFilter.etagSeed? Try using CHttpCacheFilter.etagSeedExpresiion instead. It will be evaluated directly before calling an action.

The Peach, on 24 October 2012 - 10:36 AM, said:

Second question: on one of my actions I can't get the Cache-Control to be set. The browser request contains a Cache-Control: max-age=0; (for reasons to me unknown) and this *seems* to cause Cache-Control to be returned with value: no-store, no-cache, must-revalidate, post-check=0, pre-check=0. I still don't know who's outputting it (default apache behaviour?). I wonder if this is the same problem reported by Aleksdj.

I think this is due to the same problem aleksdj described. Could you perhaps c&p your settings for that filter here?

programmer /ˈprəʊgramə/, noun: a device that converts ►coffee into ►code

now, if the user tries to reach a model that has been deleted the lastModifiedException throws an error and breaks everything.
I had a look at your code and the most flexible solution would obviously be to add an additional parameter in order to throw the right exception or do something else in case the expression fails...

Probably the simplest is to have a default value to be used in case the returned expression is nothing harmful (as in my case is an empty string).

Yes. Quite frankly, you've made poor choices for your expressions. Action and model id are no good choices for etag seeds. You might even skip on that. 'share' sounds like an action that is being used to manipulate models rather than representing them. Caching such actions might not be a good idea. (on a related note: CHttpCacheFilter will only cache GET and HEAD requests anyway)

The field created implies it won't be manipulated after the models record has been saved to the database. This makes it unsuitable for the lastModified value. Is there a modified field you could use instead?

As for the state of things: I've got a patch ready that sort-of hacks around the problem with session headers by setting a header via session_cache_limiter() and immediatly overwriting it wiht a custom value. This will need some testing as I suspect the behaviour of header() and session_cache_limiter() has changed between PHP v5.3 and 5.4.

Further patches in the pipe involve impoved interoperability with CCacheDependency (hashing CCacheDependency.getDependentData() is a bit faster than hashing the entire object) and making the controller available via $controller in the expressions (which should allow for more complex yet readable code).

programmer /ˈprəʊgramə/, noun: a device that converts ►coffee into ►code