Forum Moderators: coopster

Message Too Old, No Replies

v0.11 of Conteg.include released

Content-Negotiation for PHP produced web-output : bug-fix

         

AlexK

9:05 pm on Mar 13, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



A small bugfix + amendment to (weak) eTag production; the updated class can be obtained here [webmasterworld.com].

Conteg is a RFC-Compliant PHP Class to auto-conduct Content-Negotiation on web-pages (If-Modified-Since, If-Match, If-None-Match, If-Range and so on). It essentially does for dynamic pages what Apache does for static pages. The main practical value is to lower bandwidth costs and to speed up the delivery of web-pages, principally through the use of compression-encoding and/or 304 Not Modified pages, etc.. The original release was here [webmasterworld.com], and some support is available from here [webmasterworld.com].

Changes are mostly within the private function _initResponse(), but also include a new entry within the setup parameter array:

function setup(
$param= array()// format: array( $switch => $value, ... )
)
.
Miscellaneous Variable for Weak-Etag generation (string/Empty):
'other_var' => ''

'other_var'
is designed for a situation where a misc variable can cause the content of a page to change, but the page-date remains the same. I use it myself as a login-parameter (
session_id()
is already auto-included).

Whilst checking this new variable, a bug was found (and fixed) in the handling of cases where If-None-Match was NOT tripped, but If-Modified-Since WAS (should be 200 page, not 304 as previous).

[edited by: coopster at 3:04 am (utc) on Aug. 6, 2008]

bobmark

7:37 pm on Mar 20, 2006 (gmt 0)

10+ Year Member



I installed Conteg and it works great (and passes the the validation test on the Cachability engine on web-caching.com).

The only problem I encountered is that while I have zlib on my host, the script Conteg returns an error code from the "else if" starting on line 713 line "Conteg::setup: zlib.output_compression activated.', E_USER_NOTICE"

This appears at the bottom of any page where conteg is included.

If I am reading the message correctly it seems to simply be a notice that zlib.output_compression was activated and I assume it appears because somehow zlib wasn't activated in the normal way.

I "solved" this by the crude method of commenting out the line of code that generates this notice.

My only question would be: Is there something I can do to actually fix the problem as opposed to just suppress the message?

Conteg appears to function fine so I assume it is ok to run it this way.

Thanks

AlexK

9:21 pm on Mar 20, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



This is the code snippet starting at line 713, with the precise line raising the error highlighted:
if( isset( $param[ 'use_accept_encode' ])) {// FALSE, 0-9 or TRUE
if( $param[ 'use_accept_encode' ] === FALSE ) {// no compression attempt
$this->_noAcceptEncode= TRUE;
$this->level= 0;
} else {
// sanity checks
if(!extension_loaded( 'zlib' )) {
$this->_noAcceptEncode= TRUE;
$this->level= 0;
$this->_trigger_error( 'Conteg::setup: zlib required for compression.', E_USER_NOTICE );
} elseif( ini_get( 'zlib.output_compression' )!= '' ) {// compression handled externally
$this->_noAcceptEncode= TRUE;
$this->level= 0;
$this->_trigger_error( 'Conteg::setup: zlib.output_compression activated.', E_USER_NOTICE );
} elseif( ini_get( 'output_handler' ) == 'ob_gzhandler' ) {// compression handled externally
$this->_noAcceptEncode= TRUE;
$this->level= 0;
$this->_trigger_error( 'Conteg::setup: ob_gzhandler() registered.', E_USER_NOTICE );
} elseif(!function_exists( 'crc32' )) {
$this->_noAcceptEncode= TRUE;
$this->level= 0;
$this->_trigger_error( 'Conteg::setup: crc32() not found, PHP >= 4.0.1 required.', E_USER_NOTICE );
} else {
$this->_noAcceptEncode= FALSE;
if(( $this->level = $param[ 'use_accept_encode' ]) === TRUE )
$this->level= $this->getCompLevel();// load-balanced compression
}
}
}

It means that:
  1. You are using the Conteg default for compression
  2. Error reporting is set at E_ALL
  3. php.ini has the line:
    zlib.output_compression=On
    (or =(int)buffer-size), meaning that PHP will auto-compress, and therefore that Conteg must not.
The way to fix this is to:
  1. Use
    'use_accept_encode' => FALSE
    within the setup parameter array, and/or
  2. Set Error reporting below E_ALL (PHP default) and/or
  3. Alter php.ini to read
    zlib.output_compression=Off
    and restart Apache

PSError reporting: you are strongly advised to use E_ALL on test-setups, and use E_NONE on production setups.

bobmark

11:17 pm on Mar 20, 2006 (gmt 0)

10+ Year Member



Site is hosted commercially so no hope in altering php.ini but I am sure the
'use_accept_encode' => FALSE
will solve it nicely.

Thanks.

bobmark

8:03 pm on Mar 21, 2006 (gmt 0)

10+ Year Member



I have a theoretical question.

I realize defaults are defaults so Conteg's perhaps don't represent optimum values but why is last modified specified as 1 second in the future?

It would seem to my (ignorant on these matters) mind that 1 second in the past would be more logical.

Or is it that if validation is performed immediately by, for example, a SE bot, that 1 future second allows the correct response?

I find validation (via cachability engine) works most of the time and suspect the times not are a function of speed of response.

My question is mainly motivated by how SE bots (if they do validation) interpret the result.

AlexK

8:51 pm on Mar 21, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



If you look at line#638:
// Essentials - Modification + Expiry
// Modification date - Unix timestamp
if(!isset( $this->last_modified )) {// apply defaults on first call only
if( empty( $param[ 'modified' ])) $param[ 'modified' ] = $this->now;
}
if( isset( $param[ 'modified' ])) $this->last_modified = $param[ 'modified' ];
(important line highlighted) (I have made some cosmetic changes--due to be uploaded soonish, probably after CSI on Channel 5 TV--so the line numbers may differ slightly to your version)

By default (ie no

'modified' => (timestamp)
is supplied)
$last_modified
is set to the current time. If you have either:
  • A slow program, and/or
  • A Windows server
...the header Last-Modified may differ from the page (or other reference) timestamp.

I would strongly advise you to set both

'modified'
&
'expiry'
in your program at Conteg fire-up, since these are the absolute fundamentals for Content-Negotiation, and allow you to flag that page-content has changed, and to control browser- and proxy-cacheing.

PS
The mention of Windows is in there because of differences between how Windows sets file timestamps and how Unix does the same (I work under Windows at home & Linux on the server). Thus, when comparing the two there can be an entire second difference. Please note also that all of this also assumes that both reference-times are continuously reset true to the same time-server, which itself assumes that both machines make use of NTP (or is it NNTP?) (in any case, a time-server).

bobmark

9:38 pm on Mar 21, 2006 (gmt 0)

10+ Year Member



So if I understand correctly, you're saying to set parameters like:
// -------------- Start of Class Declaration --------------
class Conteg {
// public variables
// Response/Request-Header variables
...........
var $last_modified = 'SOMEDATE'; // timestamp; 1.0 rfc1945.txt section 10.10 (response header)

Where "SOMEDATE" is either a valid date format OR calculation result?

Sorry to be so dense.

AlexK

3:55 am on Mar 22, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Bobmark:
There is (or should not be!) any need to alter the Class code. Like all good classes, all changes are made to the Class via the input parameter array.

Look at the very bottom of the Class file, and you will find the Constructor parameter array, which shows every possible array value, and also the defaults that they carry when not set. In addition, setup() is prefixed with detailed help for each array value (begins line #483).

The values that I am suggesting you need to set are:

array(
'expiry' => 3600,
'modified' => NULL
)
As you see, the default for
'modified'
is
NULL
, which means that the Class will set the class-variable
$last_modified
to the current time, and at
show()
-time the Last-Modified header will be set to that value. If you are happy with that, then there is no need to read any further.

My suggestion is to implement an actual date for your pages (within your own code, not the Class-code) and to pass that date via the

'modified'
array-value. That will stop most of the SEs from re-requesting the full page-text, even though nothing has changed on the page (via an If-Modified-Since header which receives a 304 Not Modified response). That will save you pots of bandwidth.

PS
If you want to explore this further, investigate "Live HTTP Headers" (recommended), which is available for both Mozilla and FireFox. There is also a References section in the Class file, which contains links for further reading (although a bit of a brain-pain).