ExpiresByType image/jpg "access 2 years"
First... to clarify, this should probably be image/jpeg
, not image/jpg
. image/jpeg
is the official mime-type for JPEG files. Check the Content-Type
HTTP response header associated with this response. For instance, if your server is sending JPEG files with a image/jpeg
mime-type (as it should be), then the above directive is not doing anything.
Note that image/jpg
has nothing to do with the file extension (eg. .jpg
) that might be on the underlying filename. It refers to the mime-type the server is sending the resource as.
So, for the remainder of my answer, I assume this is the correct mime-type that your server is sending.
When will jpg files expire ? In 2 years or in one year (31536000 seconds) ?
The answer to this does depend on the type of request/response and what you are doing server-side. ie. Does the request map directly to a physical file or not? Since you mention "jpg files" then #1 below probably applies here (the most common scenario) and the "jpg file" will expire in 1 year.
1. Request maps directly to a physical .jpg
file
The request maps directly to a physical JPEG file on disk (either directly or via an internal rewrite*1). eg. /myimage.jpg
- which would indeed be the most common use case (ie. you are linking directly to your static resources) then the JPEG file will expire in 1 year, by the Header
directive. This is because:
<FilesMatch>
(and <Files>
) containers only match physical files.
- The
Header
directive is processed later and so will always override the Cache-Control
header that mod_expires might otherwise set.
*1 Note that you could link to (ie. request) /get-image.php
, but providing the request is internally rewritten directly to an underlying .jpg
file on disk, eg. /some-image.jpg
then the same applies.
2. Request does NOT map directly to a physical file
HOWEVER, if the request does not map to a physical file. For example, if either of the following scenarios is true (both are really the same):
You are linking to a PHP script that serves the JPEG image (either by creating it, or reading it from a different location, etc.) and there is no internal rewrite to a physical file.
href="send-image.php?name=myimage.jpg&size=medium"
You are linking to a .jpg
URL, eg. href="/myotherimage-medium.jpg"
and you are internally rewriting this to a script (like above) that generates this image and returns it to the client.
Then the JPEG image will expire in 2 years since the <FilesMatch>
directive will not apply, because the request does not map directly to a physical file.
Note that in both cases (scenario #1 and #2 above), the ExpiresByType
directive will apply, but the Header
directive will always override this if it is applied.
Actually, there is a further complication here... mod_expires sets 2 response headers Cache-Control: max-age
and Expires
. Expires
is only for old browsers, all modern browsers prioritise the Cache-Control: max-age
header. So, in case #1 above, where the request maps directly to a physical file then you'll have a conflict of headers... Cache-Control: max-age
will state that it expires in 1 year (overridden by the Header
directive), whereas the Expires
header will state that it expires in 2 years (set my mod_expires).
So, unless you have specific caching requirements*2 then use mod_expires only.
*2 mod_expires only sets the max-age
directive on the Cache-Control
header. If you need to set other directives, eg. no-store
or must-revalidate
etc. then you will need to use the Header
directive instead (or as well as).
Reference: