ExpiresByType image/jpg "access 2 years"
First... to clarify, this should probably be
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.
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
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:
<Files>) containers only match physical files.
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.
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 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.
must-revalidate etc. then you will need to use the
Header directive instead (or as well as).