user1409508
user1409508

Reputation: 623

ETag header does not return 304

I'm working currently on REST API. I wanted to check if HTTP cache is working fine, but unfortunatelly I doesn't work at all. No matter what I do, it always return HTTP code 200 while it should return 304 from what I know.

Here is my PHP code:

public function getList()
{
    $this->addHeaders(array(
        'Cache-Control' => 'public, must-revalidate, max-age=120',
        'eTag' => 'xyz123',
    ));

    $array = array(
        'foo' => 'bar',
        'nested' => array(
            'lorem' => 'ipsum',
            'dolor' => 'sit amet'
        )
    );

    $this->addHeader('Content-Length', strlen(json_encode($array, true)));

    return new JsonModel($array);
}

Response/Request

enter image description here

ETag doesn't change, so requests except first one should be served from cache. Am I wrong?

I was following these 2 articles:

I also checked with weak validator- Last-Modified but I got same problem. Browser sends correct header in Request, but I still get 200 in response

Upvotes: 5

Views: 3331

Answers (3)

Digitalkapitaen
Digitalkapitaen

Reputation: 2423

Your client is sending the Cache-Control header with a value of max-age=0. This indicates to the server that the client requests a fresh response and the server sends an HTTP 200 status code.

The Cache-Control header sent by the client is usually the result of using the developer tools in the browser and not disabling the "Disable caching" option.

Upvotes: 3

Steve E.
Steve E.

Reputation: 9353

ETag requires the server to send a 304 response back in order to trigger loading from the Cache.

In a time based cache:

  1. Client makes initial request, caches the response for a determined time
  2. In subsequent requests, if the resource is in the cache then it is used without contacting the server for that resource

In an ETag based cache:

  1. Client makes initial request, caches the response for a determined time along with the ETag from the server for that resource
  2. In subsequent requests, if the resource is in the cache then the ETag is included in a new request to the server as the If-None-Match field.
  3. The server checks the If-None-Match header and if it matches the content on the server, sends a 304 not modified which instructs the client cache to use it's local copy. If the ETag is different, then the server returns the resource as normal.

To make your code work, you need to check for the presence of the If-None-Match header in the PHP:

If(isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == 'xyz123') {
    header("HTTP/1.1 304 Not Modified");
    exit();
}

Upvotes: 7

Christian Strempfer
Christian Strempfer

Reputation: 7383

It looks like you didn't implement any logic for checking the eTag-headers. This cannot happen automatically, because the server doesn't understand the business logic and therefore cannot determine when it's time to invalidate the cache.

There is another answer, which describes the minimal setup.

Upvotes: 2

Related Questions