user1409508 user1409508 - 15 days ago 9
HTTP Question

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

Answer

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();
}