Yii Framework Forum: Caching at HTTP-Level - Yii Framework Forum

Jump to content

  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

Caching at HTTP-Level Rate Topic: ***** 2 Votes

#21 User is offline   aleksdj 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 51
  • Joined: 05-April 10

Posted 01 September 2012 - 10:35 PM

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


0

#22 User is offline   aleksdj 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 51
  • Joined: 05-April 10

Posted 01 September 2012 - 11:25 PM

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?

View Postaleksdj, 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



0

#23 User is offline   Da:Sourcerer 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,222
  • Joined: 30-March 11
  • Location:Berlin, Germany

Posted 02 September 2012 - 02:44 AM

Strange, I haven't had this yet. Can you show me the filters() method of your controller?
programmer /ˈprəʊgramə/, noun: a device that converts ►coffee into ►code
0

#24 User is offline   aleksdj 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 51
  • Joined: 05-April 10

Posted 09 September 2012 - 12:25 PM

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.

The fix:
To fix this bug you can write this code in your class:

	/**
	 * Http cache control headers. Set this to null in order to keep this
	 * header from being sent entirely.
	 * @var string
	 */
	public $cacheControl = null;
        
        const CACHE_LIMITER_PUBLIC = 'public';
        const CACHE_LIMITER_PRIVATE_NO_EXPIRE = 'private_no_expire';
        const CACHE_LIMITER_PRIVATE = 'private';
        const CACHE_LIMITER_NOCACHE = 'nocache';



and in the function to write the cache control header:


	/**
	 * Sends the cache control header to the client
	 * @see cacheControl
	 * @since 1.1.12
	 */
	protected function sendCacheControlHeader()
	{
                session_cache_limiter($this->cacheControl);
                
	}



This code is working for me perfectly.

This bug took me some hours to "chase and dig in the code" so I hope it helps :D
regards

View PostDa:Sourcerer, on 02 September 2012 - 02:44 AM, said:

Strange, I haven't had this yet. Can you show me the filters() method of your controller?

1

#25 User is offline   Da:Sourcerer 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,222
  • Joined: 30-March 11
  • Location:Berlin, Germany

Posted 10 September 2012 - 04:53 AM

Thanks for reporting this. I'll patch the filter asap.
programmer /ˈprəʊgramə/, noun: a device that converts ►coffee into ►code
0

#26 User is offline   aleksdj 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 51
  • Joined: 05-April 10

Posted 10 September 2012 - 07:38 AM

you are welcome!


View PostDa:Sourcerer, on 10 September 2012 - 04:53 AM, said:

Thanks for reporting this. I'll patch the filter asap.




0

#27 User is offline   Da:Sourcerer 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,222
  • Joined: 30-March 11
  • Location:Berlin, Germany

Posted 10 September 2012 - 07:52 AM

Damn, I messed up, I'm afraid. This won't be that easy to fix :(
programmer /ˈprəʊgramə/, noun: a device that converts ►coffee into ►code
0

#28 User is offline   aleksdj 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 51
  • Joined: 05-April 10

Posted 10 September 2012 - 10:13 AM

why not? you are only setting the session_cache_limiter arent you?

View PostDa:Sourcerer, on 10 September 2012 - 07:52 AM, said:

Damn, I messed up, I'm afraid. This won't be that easy to fix :(

0

#29 User is offline   Da:Sourcerer 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,222
  • Joined: 30-March 11
  • Location:Berlin, Germany

Posted 10 September 2012 - 10:50 AM

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
0

#30 User is offline   The Peach 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 62
  • Joined: 08-October 09
  • Location:London, UK

Posted 24 October 2012 - 10:36 AM

Hi, first of all thanks to Da:Sourcerer for this extension.

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.

Best,
peach.
0

#31 User is offline   Da:Sourcerer 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,222
  • Joined: 30-March 11
  • Location:Berlin, Germany

Posted 24 October 2012 - 10:44 AM

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

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.

View PostThe 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
0

#32 User is offline   The Peach 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 62
  • Joined: 08-October 09
  • Location:London, UK

Posted 24 October 2012 - 11:35 AM

View PostDa:Sourcerer, on 24 October 2012 - 10:44 AM, said:

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


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


current configuration for the filter is the following
    public function filters() {
        return array(
            array(
                'CHttpCacheFilter',
                'cacheControl' => 'private; max-age=31536000',
                'etagSeedExpression' => 'Yii::app()->getController()->action->id',
            ),
        );
    }


Now the etagSeedExpression sets the etag for each single actions, which is fine.
Still there's only one action which ignores it completely (Apparently as specified before).
0

#33 User is offline   The Peach 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 62
  • Joined: 08-October 09
  • Location:London, UK

Posted 25 October 2012 - 04:37 AM

As a side note, do you think it's worth adding Vary header in this filter? Or would it be a better place for it?
0

#34 User is offline   Da:Sourcerer 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,222
  • Joined: 30-March 11
  • Location:Berlin, Germany

Posted 25 October 2012 - 03:21 PM

View PostThe Peach, on 25 October 2012 - 04:37 AM, said:

As a side note, do you think it's worth adding Vary header in this filter? Or would it be a better place for it?

This is a bit problematic. Vary can contain many things and we do not (yet) have an infrastructure for managing response headers, so there's a chance of overwriting something important.

Working on a patch now, btw.
programmer /ˈprəʊgramə/, noun: a device that converts ►coffee into ►code
0

#35 User is offline   The Peach 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 62
  • Joined: 08-October 09
  • Location:London, UK

Posted 26 October 2012 - 06:45 AM

I see what you mean... and that's probably OK for the meantime.

On the other end I'm just facing another problem on top of everything.
So basically for the view pages of my model I'm using a similar config:
            array(
                'CHttpCacheFilter + view, share',
                'cacheControl' => 'private; max-age=31536000',
                'etagSeedExpression' => "Yii::app()->getController()->action->id . \$_GET['id']",
                'lastModifiedExpression' => "Yii::app()->db->createCommand()->select('created')->from('doodle')->where('id=:id', array(':id'=>\$_GET['id']))->queryScalar()",
            ),


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).

Got any ideas?
0

#36 User is offline   Da:Sourcerer 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,222
  • Joined: 30-March 11
  • Location:Berlin, Germany

Posted 27 October 2012 - 10:05 AM

View PostThe Peach, on 26 October 2012 - 06:45 AM, said:

Got any ideas?

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
0

#37 User is offline   Da:Sourcerer 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,222
  • Joined: 30-March 11
  • Location:Berlin, Germany

Posted 29 October 2012 - 04:42 AM

A fix is ready.
programmer /ˈprəʊgramə/, noun: a device that converts ►coffee into ►code
0

#38 User is offline   Da:Sourcerer 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,222
  • Joined: 30-March 11
  • Location:Berlin, Germany

Posted 10 November 2012 - 05:13 PM

Ok, the fix has just been merged :)
programmer /ˈprəʊgramə/, noun: a device that converts ►coffee into ►code
0

Share this topic:


  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users