Re: [PHP] 304 Not Modified header not working within a class

2010-01-23 Thread Camilo Sperberg
Problem solved!!!

Everything was working ok with PHP. My class was working ok. The engineering
and logic behind PHP was working. So... what was the problem? Apache...
well, it wasn't a problem, but a misconfiguration or better said, a
mis-optimization.
In my first message, I stated: (quote)

> there is no way I can send a 304 Not Modified header, when the data is
> *over* ~100 bytes.
>

After 8 hours of working with this problem (which included sniffering and a
lot of workarounds), and while I was smoking my final cigarrette before
going to bed, I remembered that some time ago (well, some time like 2 years
ago xD), I had enabled mod_disk_cache, with the following configuration:

  CacheRoot /tmp/apachecache/
  CacheEnable disk /
  CacheDirLength 1
  CacheDirLevels 5
  CacheMaxFileSize 128000
  *CacheMinFileSize 100*


I commented that part, restarted Apache and bingo Instantly I had an 304
header.
What do I think the problem was? Whenever Apache received a request, it
handled it directly from _his_ cache and simply omitted what PHP was telling
him to do. The weird thing was that the class entered the 304 header part,
but Apache always ended up sending an 200 OK header and then the CSS. In
first place it shouldn't have sended the CSS because when I entered the 304
part, it should have died. It simply couldn't send any other output. (And
that was why I sniffered, if it shouldn't send the CSS; he must have been
send some kind of error, but my surprise was really big when I saw that the
raw data was just plain CSS, no other data was present).
Why was Apache then sending a 304 whenever the data was under the 100 byte
limit? Because he didn't have it in his cache and was obeying what PHP told
him to do. (This configuration created a cache whenever the file size is
between the 100 and 128000 bytes).

Anyway... now I will be publishing the class soon on phpclasses.org under
the BSD license. I'll work now on documentation and code cleanup but
whenever it is ready I will leave the link in this same list (if it is
allowed) xD

Greetings, a lot of thanks to Richard for his code and Rene for his
suggestion to take a look at Apache and good night :P (Despite being 7AM xD)


On Wed, Jan 20, 2010 at 21:16, Camilo Sperberg wrote:

>
>
> On Wed, Jan 20, 2010 at 04:34, richard gray  wrote:
>
>>
>> Camilo Sperberg wrote:
>>
>>> Hi list, my first message here :)
>>>
>>> To the point: I'm programming a class that takes several CSS files,
>>> parses,
>>> compresses and saves into a cache file. However, I would like to go a
>>> step
>>> further and also use the browser cache, handling the 304 and 200 header
>>> types myself.
>>>
>>> Now, what is the problem? If I do it within a function, there is
>>> absolutely
>>> no problem, everything works like a charm. However, when I implement that
>>> same concept into my class, there is no way I can send a 304 Not Modified
>>> header, when the data is *over* ~100 bytes.
>>>
>>>
>>>
>> Hi Camilo
>>
>> For what it is worth I have implemented cacheing in a class and for me the
>> 304 not modified header gets sent fine ... some example headers output is
>> below together with the relevant code snippet..
>>
>> // See if client sent a page modified header to see if we can
>> // just send a not modified header instead
>> if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
>> $_SERVER['HTTP_IF_MODIFIED_SINCE'] == self::$_gmmodtime) {
>>
>>   header('HTTP/1.1 304 Not Modified');
>>   return null;
>> }
>>
>> if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
>> stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == self::$_etag) {
>>
>>   header('HTTP/1.1 304 Not Modified');
>>   return null;
>> }
>>
>>
>> HTTP/1.x 304 Not Modified
>> Date: Wed, 20 Jan 2010 07:21:32 GMT
>> Server: Apache/2.2.11 (Ubuntu)
>> Connection: Keep-Alive
>> Keep-Alive: timeout=5, max=1000
>> Etag: 444fbd9951f540ec1b6928db864c10dc
>> Expires: Sun, 24 Jan 2010 06:16:06 GMT
>> Cache-Control: public, must-revalidate
>> Vary: Accept-Encoding
>>
>> I hope it helps..
>>
>> Regards
>> Rich
>>
>
> I'll try this (and some other things I recently thought about) when I get
> back home on friday :) I'll keep you updated.
>
> Thanks!
>
>
> --
> Mailed by:
> UnReAl4U - unreal4u
> ICQ #: 54472056
> www1: http://www.chw.net/
> www2: http://unreal4u.com/
>



-- 
Mailed by:
UnReAl4U - unreal4u
ICQ #: 54472056
www1: http://www.chw.net/
www2: http://unreal4u.com/


Re: [PHP] 304 Not Modified header not working within a class

2010-01-20 Thread Camilo Sperberg
On Wed, Jan 20, 2010 at 04:34, richard gray  wrote:

>
> Camilo Sperberg wrote:
>
>> Hi list, my first message here :)
>>
>> To the point: I'm programming a class that takes several CSS files,
>> parses,
>> compresses and saves into a cache file. However, I would like to go a step
>> further and also use the browser cache, handling the 304 and 200 header
>> types myself.
>>
>> Now, what is the problem? If I do it within a function, there is
>> absolutely
>> no problem, everything works like a charm. However, when I implement that
>> same concept into my class, there is no way I can send a 304 Not Modified
>> header, when the data is *over* ~100 bytes.
>>
>>
>>
> Hi Camilo
>
> For what it is worth I have implemented cacheing in a class and for me the
> 304 not modified header gets sent fine ... some example headers output is
> below together with the relevant code snippet..
>
> // See if client sent a page modified header to see if we can
> // just send a not modified header instead
> if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
> $_SERVER['HTTP_IF_MODIFIED_SINCE'] == self::$_gmmodtime) {
>
>   header('HTTP/1.1 304 Not Modified');
>   return null;
> }
>
> if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
> stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == self::$_etag) {
>
>   header('HTTP/1.1 304 Not Modified');
>   return null;
> }
>
>
> HTTP/1.x 304 Not Modified
> Date: Wed, 20 Jan 2010 07:21:32 GMT
> Server: Apache/2.2.11 (Ubuntu)
> Connection: Keep-Alive
> Keep-Alive: timeout=5, max=1000
> Etag: 444fbd9951f540ec1b6928db864c10dc
> Expires: Sun, 24 Jan 2010 06:16:06 GMT
> Cache-Control: public, must-revalidate
> Vary: Accept-Encoding
>
> I hope it helps..
>
> Regards
> Rich
>

I'll try this (and some other things I recently thought about) when I get
back home on friday :) I'll keep you updated.

Thanks!

-- 
Mailed by:
UnReAl4U - unreal4u
ICQ #: 54472056
www1: http://www.chw.net/
www2: http://unreal4u.com/


Re: [PHP] 304 Not Modified header not working within a class

2010-01-19 Thread richard gray


Camilo Sperberg wrote:

Hi list, my first message here :)

To the point: I'm programming a class that takes several CSS files, parses,
compresses and saves into a cache file. However, I would like to go a step
further and also use the browser cache, handling the 304 and 200 header
types myself.

Now, what is the problem? If I do it within a function, there is absolutely
no problem, everything works like a charm. However, when I implement that
same concept into my class, there is no way I can send a 304 Not Modified
header, when the data is *over* ~100 bytes.

  

Hi Camilo

For what it is worth I have implemented cacheing in a class and for me 
the 304 not modified header gets sent fine ... some example headers 
output is below together with the relevant code snippet..


// See if client sent a page modified header to see if we can
// just send a not modified header instead
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && 
$_SERVER['HTTP_IF_MODIFIED_SINCE'] == self::$_gmmodtime) {

   header('HTTP/1.1 304 Not Modified');
   return null;
}

if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && 
stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == self::$_etag) {

   header('HTTP/1.1 304 Not Modified');
   return null;
}


HTTP/1.x 304 Not Modified
Date: Wed, 20 Jan 2010 07:21:32 GMT
Server: Apache/2.2.11 (Ubuntu)
Connection: Keep-Alive
Keep-Alive: timeout=5, max=1000
Etag: 444fbd9951f540ec1b6928db864c10dc
Expires: Sun, 24 Jan 2010 06:16:06 GMT
Cache-Control: public, must-revalidate
Vary: Accept-Encoding

I hope it helps..

Regards
Rich

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] 304 Not Modified header not working within a class

2010-01-19 Thread Rene Veerman
ok, you might wanna re-ask on an apache list in that case..

On Wed, Jan 20, 2010 at 6:48 AM, Camilo Sperberg  wrote:
>
>
> On Wed, Jan 20, 2010 at 02:33, Rene Veerman  wrote:
>>
>> if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) AND
>> strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified) {
>>
>>
>> shouldn't that be
>>
>> strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $last_modified)
>>
>> ?
>
> Now that I think about it... yes; but I send the last modified header anyway
> the first time (when $_SERVER['HTTP_IF_MODIFIED_SINCE'] == null):
> header('Last-Modified: '.gmdate('D, d M Y H:i:s',$last_modified).' GMT');
>
> So if it isn't exactly equal, then the browser cache simply doesn't have the
> latest version. It is impossible anyway that the browser can have a newer
> version that doesn't previously exist on the server.
> My best guess is that it doesn't affect the process: when I implement that
> code in my class, it enters that part (meaning all the comparisons are ok)
> but afterwards it keeps sending an "200 OK" header when I explicitly tell
> Apache to send the "304 Not Modified" one.
>
> Greetings and thanks for sharing :)
>
> --
> Mailed by:
> UnReAl4U - unreal4u
> ICQ #: 54472056
> www1: http://www.chw.net/
> www2: http://unreal4u.com/
>

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] 304 Not Modified header not working within a class

2010-01-19 Thread Camilo Sperberg
On Wed, Jan 20, 2010 at 02:33, Rene Veerman  wrote:

> if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) AND
> strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified) {
>
>
> shouldn't that be
>
> strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $last_modified)
>
> ?
>

Now that I think about it... yes; but I send the last modified header anyway
the first time (when $_SERVER['HTTP_IF_MODIFIED_SINCE'] == null):
header('Last-Modified: '.gmdate('D, d M Y H:i:s',$last_modified).' GMT');

So if it isn't exactly equal, then the browser cache simply doesn't have the
latest version. It is impossible anyway that the browser can have a newer
version that doesn't previously exist on the server.
My best guess is that it doesn't affect the process: when I implement that
code in my class, it enters that part (meaning all the comparisons are ok)
but afterwards it keeps sending an "200 OK" header when I explicitly tell
Apache to send the "304 Not Modified" one.

Greetings and thanks for sharing :)

-- 
Mailed by:
UnReAl4U - unreal4u
ICQ #: 54472056
www1: http://www.chw.net/
www2: http://unreal4u.com/


[PHP] 304 Not Modified header not working within a class

2010-01-16 Thread Camilo Sperberg
Hi list, my first message here :)

To the point: I'm programming a class that takes several CSS files, parses,
compresses and saves into a cache file. However, I would like to go a step
further and also use the browser cache, handling the 304 and 200 header
types myself.

Now, what is the problem? If I do it within a function, there is absolutely
no problem, everything works like a charm. However, when I implement that
same concept into my class, there is no way I can send a 304 Not Modified
header, when the data is *over* ~100 bytes.

What is funnier is that it enters the 304 function within the class, but
apparently it doesn't respect that and ends sending a 200 OK header anyway.
Let's take a look at the code:

This is a simple test scenario implemented within a little file just to
proof and make sure it is working before I adapt the code in the class.
Everything is ok here:

define('TIME_BROWSER_CACHE','3600');
$last_modified = filemtime('blabla.css');

if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) AND
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified) {
  header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified',TRUE,304);
  header('Pragma: public');
  header('Last-Modified: '.gmdate('D, d M Y H:i:s',$last_modified).' GMT');
  header('Cache-Control: max-age='.TIME_BROWSER_CACHE.', must-revalidate,
public');
  header('Expires: '.gmdate('D, d M Y H:i:s',time() + TIME_BROWSER_CACHE).'
GMT');
  die();
}
header('Content-type: text/css; charset=UTF-8');
header('Pragma: public');
header('Last-Modified: '.gmdate('D, d M Y H:i:s',$last_modified).' GMT');
header('Cache-Control: max-age='.TIME_BROWSER_CACHE.', must-revalidate,
public');
header('Expires: '.gmdate('D, d M Y H:i:s',time() + TIME_BROWSER_CACHE).'
GMT');

Now the class (simplified):

  public function printme($method = 'file') {
if($this->qCSS > 0 AND ($method == 'file' OR $method = 'inline')) {
  if ($method == 'file') {
$last_modified = filemtime(CACHE_LOCATION);
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) AND
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified AND
$this->valid_cache()) {
  // $this->valid_cache() determines if the internal CSS cache is
still valid. If it is, it returns TRUE, else FALSE
  header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified', TRUE,
304);
  // also tried sending header('HTTP/1.1 304 Not Modified'); but
that didn't do the trick
  header('Pragma: public'); // Useless? Maybe, but the function
works with or without it.
  header('Last-Modified: '.gmdate('D, d M Y H:i:s',$last_modified).'
GMT'); // Always good to send this too.
  header('Cache-Control: max-age='.TIME_BROWSER_CACHE); // idem
  header('Expires: '.gmdate('D, d M Y H:i:s',time() +
TIME_BROWSER_CACHE).' GMT'); // idem
  $fp = fopen('cache/hi.txt','a'); // Just to check stuff
  fwrite($fp,'header 304 sended, let\'s die'."\n"); // It logs this
without problem, which means it really enters this function when needed.
  fclose($fp);
  die(); // Terminate script execution or else it would continue to
the bottom, which isn't necessary.
}
header('Content-type: text/css; charset='.CHARSET); // From here on,
it applies only if we need to send the CSS.
if (USE_BROWSER_CACHE) { // Constant [TRUE|FALSE] which defines
whether to use the browser cache or not.
  header('Pragma: public');
  header('Last-Modified: '.gmdate('D, d M Y H:i:s',$last_modified).'
GMT');
  header('Cache-Control: max-age='.TIME_BROWSER_CACHE);
  header('Expires: '.gmdate('D, d M Y H:i:s',time() +
TIME_BROWSER_CACHE).' GMT');
}
// Rest of the function: get the CSS and echo it, within an
ob_start('ob_gzhandler');
()
$content_length = filesize(CACHE_LOCATION);
if (extension_loaded('zlib')) $content_length = ob_get_length();
header('Content-Length: '.$content_length); // Necesary if we don't
want to send the CSS in chunks.
if (extension_loaded('zlib')) ob_end_flush();

Other useful information:
- Code #1 returns an 304 when it is needed, even when the CSS size is over
50kb. (Haven't test any CSS over that size yet)
- Code #2 goes into the 304 part but doesn't send the 304, unless the total
CSS size is under 100 bytes.
- Tried also with ETags, didn't worked either.
- Tried increasing or decreasing TIME_BROWSER_CACHE, didn't worked.
- Tried with/without Pragma header, Last-Modified header, Cache-Control
header, Expires header, all the 16 posibilities. None of them worked.
- Tried with getallheaders() and making the proper changes.
- Tried with/without ob_gzhandler.
- Tried with/without ob_start().
- Tried with all options on/off within Last-Modified header and
Cache-Control header (must-revalidate, public, etc). None of them worked.
- Tried searching on Google, reading the comments on php.net and searching
within this list. Nothing like this came up.
- I've be