When sending the cache control header Cache-Control: no-cache, must-revalidate
along with a Last-Modified
timestamp, the browser is required to send along an If-Modified-Since
header for the next request to the same URL.
The server then is entitled to return HTTP/1.1 304 Not modified
in case the content didn't change and the stored copy may still be used.
<?php
$time = 'Wed, 21 Oct 2016 07:28:00 GMT';
header('Cache-Control: no-cache, must-revalidate');
header('Last-Modified: ' . $time );
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $time === $_SERVER['HTTP_IF_MODIFIED_SINCE']) {
http_response_code(304);
header('X-MODIFIED-SINCE: MATCH');
die();
}
http_response_code(200);
header('X-CONTENT-RETURN: YES');
echo '<a href="/index.php">link to index.php</a>';
Request Headers
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-DE,de;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache
Response Headers
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Sun, 24 Mar 2019 16:11:16 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/7.3.3
Cache-Control: no-cache, must-revalidate
Last-Modified: Wed, 21 Oct 2016 07:28:00 GMT
X-CONTENT-RETURN: YES
Request Headers
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-DE,de;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/index.php
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
If-Modified-Since: Wed, 21 Oct 2016 07:28:00 GMT
Response Headers
HTTP/1.1 304 Not Modified
Server: nginx/1.14.2
Date: Sun, 24 Mar 2019 16:14:26 GMT
Connection: keep-alive
X-Powered-By: PHP/7.3.3
Cache-Control: no-cache, must-revalidate
Last-Modified: Wed, 21 Oct 2016 07:28:00 GMT
X-MODIFIED-SINCE: MATCH
Perfect. That's the way it's supposed to work. Now let's try the same thing without NGINX
php -S 127.0.0.1:8080 index.php
Request Headers
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-DE,de;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Response Headers
HTTP/1.1 200 OK
Host: 127.0.0.1:8080
Date: Sun, 24 Mar 2019 16:18:54 +0000
Connection: close
X-Powered-By: PHP/7.3.3
Cache-Control: no-cache, must-revalidate
ETag: some-etag-value
Last-Modified: Wed, 21 Oct 2016 07:28:00 GMT
X-CONTENT-RETURN: YES
Content-type: text/html; charset=UTF-8
Request Headers
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-DE,de;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1:8080/index.php
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
What happend to the If-Modified-Since
header?
Of course it works in Chromium & Epiphany. ;-)
So, is this a Bug in
- My Script
- The PHP CLI Server
- Firefox
I wouldn't know how it could be a bug in my small sample script as it works when run via nginx+php-fpm and with either server for chrome/chromium and epiphany.
The only difference in the headers I can see is the Format used for the Date
response header, the other headers are ( should be?) unrelated. Or not?
It might be an overly picky Firefox not liking the date format +0000
rather than GMT
. It would be easy to simply set a custom Date
header, of course. Problem is: PHP's Cli Server adds its own no matter what. Yes, it will have two Date
header lines in that case. That's not helping ;)
Yes, I'm pretty sure
Date
headers must be in GMT and+0000
is invalid.