1

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?

Steven
  • 17,796
  • 13
  • 66
  • 118
  • What about something like: `` - [Reference](http://stackoverflow.com/questions/18676012/understanding-htaccess-filesmatch-code) (FilesMatch in general, **note** above isn't tested) – Darren Jun 20 '14 at 01:16
  • @Darren That doesn't work, unfortunately. It appears that it's ignoring all but the file name itself (`should-expire.png`) for the purpose of `FilesMatch`, rather than considering the entire relative path. – Steven Jun 20 '14 at 01:21
  • So you're saying you need **only** the files in `uploads` to expire/ have the rule applied to them? – Darren Jun 20 '14 at 01:22
  • Have you tried `` – anubhava Jun 20 '14 at 03:43

2 Answers2

0

.htaccess file configures can be inherited to subdirectories.

  1. add next option to ./.htaccess

    RewriteOptions inherit
    
  2. make ./uploads/.htaccess

  3. add options for uploads directory to ./uploads/.htaccess like this

    <FilesMatch ".*">
        ExpiresDefault A604800
    </FilesMatch>
    
gilchris
  • 1,231
  • 17
  • 24
  • 1
    The OP had already stated they had tried a secondary `.htaccess` file in the `/uploads` subdirectory - which worked OK - but they were looking for a solution with just a single `.htaccess` file in the root. You don't need the `` wrapper here. And the `RewriteOptions` directive is not required either, unless the OP was also including mod_rewrite directives in the `/uploads/.htaccess` file. – MrWhite May 10 '19 at 11:34
0

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.

MrWhite
  • 43,179
  • 8
  • 60
  • 84