My host's file structure looks like this:
.
./.htaccess
./index.html
./should-not-expire.png
./uploads/should-expire.png
./uploads/should-expire.jpg
How can I ensure that files under the uploads
directory are all served with a far future expires header, without serving such a header for index.html
or should-not-expire.png
?
I've reviewed the sections docs that discuss the <Directory>
, <Files>
, and <Location>
blocks, and it seems like Directory
and Location
are not allowed in .htaccess
, and Files
matches only the file name and not any part of the path. For instance, this directive doesn't seem to send the desired headers:
<FilesMatch "uploads">
ExpiresDefault A604800
</FilesMatch>
It seems like one resort would be to introduce another .htaccess
file in the uploads
directory. That seems to work fine, but is there any way to do this with just the sole .htaccess
?
.htaccess file configures can be inherited to subdirectories.
add next option to ./.htaccess
RewriteOptions inherit
make ./uploads/.htaccess
add options for uploads directory to ./uploads/.htaccess like this
<FilesMatch ".*">
ExpiresDefault A604800
</FilesMatch>
If you are on Apache 2.2 and you want to use mod_expires to target a subdirectory then I think you need to use another .htaccess
file in that subdirectory, as you suggest.
Alternatively, you can set an environment variable (using SetEnvIf
) if the request maps to that subdirectory and manually set the appropriate Cache-Control
header (using the mod_headers Header
directive) if that environment variable is set. For example:
SetEnvIf Request_URI ^/uploads/ uploads_dir
Header set Cache-Control "max-age=604800" env=uploads_dir
mod_headers will override mod_expires (since it executes later in the request). So, if you have different caching requirements for different file types, you will need to repeat the Header
directive in appropriate <FilesMatch>
containers for the different file types as required. For example:
<FilesMatch "\.(jpg|png|gif)$">
Header set Cache-Control "max-age=2592000" env=uploads_dir
</FilesMatch>
However, if you are on Apache 2.4 then you can simply use an Apache expression with an <If>
container to examine the requested URL. For example:
<If "%{REQUEST_URI} =~ m#^/uploads/#">
ExpiresDefault A604800
</If>
Whilst the <If>
expression is evaluated early, the contents of the <If>
section are merged late, so will override the ExpiresDefault
defined outside of the <If>
block, regardless of the order of directives in the file.