budgetneon / pagecache

Page Level Cache For OpenCart

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

undefined function http_response_code()

pongo opened this issue · comments

http_response_code() function was introduced in PHP 5.4. For lower version of PHP you can include this function http://php.net/manual/en/function.http-response-code.php#107261

Unfortunately, that solution is a little broken. It doesn't detect, for example, opencart doing this:

header('HTTP/1.1 404 Not Found');

It will just return "200".

Nonetheless, I'll see if I can come up with a better solution. Probably parsing headers_list().

Sadly, there's not a good solution for this.

We use http_response_code() to ensure that we only cache responses with a status of "200 OK". This keeps us from, for example, caching 5XX server errors (that might be temporary), 404 Not Found, etc.

PHP5.3 does not allow any real way to get the http status of the current request. For example, the status line, even though it's a header, is specifically hidden in the headers_list() call.

I tried to get the information I needed from opencart. That initially seemed promising, as we already have the opencart response object in the code. Sadly, while the response object does have access to the data I need, it's marked as a private attribute.

All that said, I did just push a change so that it will run on PHP5.3. What it does now is only leverage http_response_code() if it's available. That means, though, if you run it on PHP5.3, it will cache 404 errors, 5XX errors, etc. If http_response_code() is available, it will only cache responses that are "200 OK".

I do not recommend running this under PHP5.3. See the "Requirements" section of readme.md for details.

Why we can't open system/library/response.php and make $headers array public?

Most of the major hosting companies have switched to PHP5.4, as have the major linux distributions, including Debian, which is usually slow to adopt new versions.

Also see this: http://forum.opencart.com/viewtopic.php?f=24&t=130933

I don't want to have to add a dependency on vqmod, or more changes to core opencart files. I'd like to keep this page cache relatively simple.

That said, yes, it would be fairly easy for anyone to make that change to response.php and then a few small changes in this code.

My hosting have only 5.3. I change response.php, what i need change in pagecache.php?

I'll see if I have time to make a one-off pagecache.php for you, but I can't do it today. Maybe tomorrow or friday. Thanks..

Okay...

  1. You can put the headers attribute in response.php back to private.

  2. Add the following function into response.php:

public function http_response_code() {
    foreach ($this->headers as $header) {
        if (preg_match("#^HTTP/\S+\s+(\d\d\d)#i",$header,$matches)) {
            return $matches[1];
        }
    }
    return 200;
}
  1. Within pagecache.php, change this:
    if (function_exists('http_response_code')) {
        if (http_response_code() != 200) {
            return false;
        }
    }

To this:

   if (method_exists($response,'http_response_code')) {
        if ($response->http_response_code() != 200) {
            return false;
        }
    }

Thank you very much! All works.

In the response.php the code goes into the "class Response { }" ?

Yes, it's a new method within the class.

You could, for example, put it in just after:

    public function addHeader($header) {
        $this->headers[] = $header;
    }

That said, I would highly recommend just upgrading to PHP5.4.

Php 5.3 is officially end of life, and no longer supported.

http://php.net/eol.php

Yes I want to upgrade, but my hosting company want's to upgrade the whole OS on my VPS. The OC is fully PHP 5.4 compatible?

I would be very grateful if you could confirm my manual pagecache installation in index.php:

http://pastebin.ca/2887517

In your pastebin, there's an issue. It should look like this at the bottom:

// Output
$response->output();   

if ($pagecache->OkToCache()) {                                  //PAGECACHE
    $pagecache->CachePage($response);                           //PAGECACHE
}                                                               //PAGECACHE

You have the order reversed.

Thank you, I fixed that.

My final pagecache.php:

     if (method_exists($response,'http_response_code')) {
        if ($response->http_response_code() != 200) {
            if (function_exists('php_sapi_name')) {
                // litespeed is broken, http_response_code()
                // returns '' when it should return 200
                if (php_sapi_name() == 'litespeed') {
                    if (http_response_code() != '') {
                        return false;
                    }
                }
            } else { 
                return false;
            }     
        }
    }

Hmmm, I just tested today, but 404 pages are still cached.

Looks like there's some missing logic, yes.

Change your snipped above to:

 if (method_exists($response,'http_response_code')) {
    if ($response->http_response_code() != 200) {
        if (function_exists('php_sapi_name')) {
            // litespeed is broken, http_response_code()
            // returns '' when it should return 200
            if (php_sapi_name() == 'litespeed') {
                if (http_response_code() != '') {
                    return false;
                }
            } else {
                return false;
            }
        } else { 
            return false;
        }     
    }
}

And, also, clear the cache. It will serve the cached file if it's sitting there and not expired.

Superb, it is working now. 👍