I'm running an Apache web server, serving up large static images off of the file system. I've configured the server to return a valid cache header, like so: Header merge Cache-Control "public, max-age=31536000, immutable"
That's all well and good, but when the user reloads the image in the browser, Apache never returns a 304 Not Modified
response.
I ran this curl command (I've changed the host name for confidentiality reasons):
curl -o /tmp/image.png -v -u test:example http://blah.example.com/static/images/covers/436g2gu94kxin4x7
Here are the request headers from curl.
GET /static/images/covers/436g2gu94kxin4x7 HTTP/1.1
Host: blah.example.com
Authorization: Basic dGVzdDpleGFtcGxl
User-Agent: curl/7.64.1
Accept: */*
If-Modified-Since: Thu, 30 Apr 2020 02:21:47 GMT
I expected a 304 response, but instead I got:
HTTP/1.1 200 OK
Date: Fri, 28 Aug 2020 04:59:54 GMT
Server: Apache/2.4.25 (Debian)
Content-Type: image/png
Content-Length: 3115720
Last-Modified: Thu, 30 Apr 2020 02:21:47 GMT
Vary: Accept-Encoding
Cache-Control: public, max-age=31536000, immutable
I've read the Apache Caching Guide, but none of it seems relevant to this situation… it's all about configuring Apache's own cache, either in memory or on disk, especially to support cases where Apache is serving as a reverse proxy for an origin server.
But in this case, the files are sitting there on the local disk already. There is no origin server. I don't want/need Apache to store a separate "cached" copy of the file; I just want Apache to notice that the Last-Modified
date of the file on disk matches the If-Modified-Since
date and return 304 Not Modified
in that case.
How do I set this up? Do I have to make Apache store its own separate cached copy of the files in order to enable conditional GETs? (That will be a very large cache, presumably stored on disk, which is a total waste.)
First, is it really not caching?
It's possible curl could be your issue. I tired your code on a URL I know to return 304, and it always returns 200 using your code above. Did you try a web browser's developer tools? As long as "disable caching" is unchecked, you should be able to refresh your URL and see it return 304 on the second refresh.
Second, it could be an Apache bug
I don't see an ETag header in your results. Assuming Apache really isn't adding this, then you can probably disregard this. But you still might try adding this to your Apache settings, just in case:
(Be sure to enable the headers mod with
a2enmod headers
.)Or, better still, if you're on Apache version 2.4.42 and later (
apache2 -v
), you can instead try this in your settings:This issue was caused by the deflate module adding the compression method to the end of the ETag. This caused Apache to ignore caching and always return 200. In their own words, this:
Apache Module mod_deflate
So disabling that can resolve some caching problems.