4

I've got an Apache vhost which performs a number of rewrite operations (using mod_rewrite) on the requested URLs. Some of these RewriteRule calls redirect the browser to other hosts (using 301 and 302 redirections).

I have set a default expiry of 1 second in that vhost file:

ExpiresActive On
ExpiresDefault "access plus 1 second"

and accordingly, all of the redirections include this header:

Cache-Control: max-age=1

Now what I'm trying to do is to output a different caching header in the case of one particular redirection. I want most of the redirections (the 302s) to continue have a 1 second expiry, but for one of them (a 301), I'd like to use a 1-day expiry instead.

Is this doable?

5 Answers 5

7

There is a way to do this, but not with mod_expires. Instead you must set an environment variable using mod_rewrite and then conditionally add the right caching headers with mod_headers as described in Mark S. Kolich: Set the Cache-Control and Expires Headers on a Redirect with mod_rewrite.

So my final solution looks like this:

RewriteRule ... [last,redirect=301,env=longexpiry:1]
RewriteRule ... [last,redirect=302,env=nocache:1]

Header always set Cache-Control "no-store, no-cache, must-revalidate" env=nocache
Header always set Cache-Control "max-age=86400" env=longexpiry

Make sure you don't have a default expiry set by mod_expires though or you will end up with duplicate headers.

4
  • Thanks, I was having the same problem (trying to use a redirect to watermark hotlinked images) and the redirect was being cached. That fixed it.
    – Lendrick
    Mar 22, 2012 at 17:17
  • 1
    It should be noted that the always keyword can be critical, because the documentation notes numerous conditions where the default set won't apply, cf. httpd.apache.org/docs/current/mod/mod_headers.html#header Mar 29, 2017 at 10:59
  • The name of the variable set by RewriteRule gets rewritten. In your example, what one must check for when setting the header is not the original longexpiry, but REDIRECT_LONGEXPIRY.
    – Mikhail T.
    Oct 22, 2017 at 2:57
  • as mentioned by Josip, the always shouldn't be here as it forces the header on all responses, when not set its only added on 2xx responses. And about duplicate headers... if they are not contradictory, it's acceptable and valid to have Cache-Control on multiple times. Aug 27, 2019 at 6:04
1

Expanding on @Francois Marier's answer, I needed a rewrite rule that looks like this without the 30X redirect :

RewriteRule ^version/[0-9a-z\-]*/(.*)$ /foo/$1 [E=versioncache:1]

And since I wanted to use versioncache in a Header set rule, it needs to be:

Header always set Cache-Control "max-age=86400" env=REWRITE_versioncache

How long do you think it to me to figure out why the obvious ... env=versioncache didn't work? Thanks to this answer for the hint on apache prepending REWRITE_.

1
  • I think that should be REDIRECT_ rather than REWRITE_ - that's what worked for me anyway and what the linked article seems to be about. Jan 7, 2017 at 13:55
0

For this you need to make another virtual host that has the different settings, and for the redirects you want under "this situation" use that vHost instead. This is not PHP code, it's Apache language. Sorry. There are no if-thens.

0

You could try using SetEnvIf directive from Apache mod_setenvif. Something like this (not tested):

SetEnvIf Request_URI \.gif EXPIRES1DAY
Header set Cache-Control max-age=86400 env=EXPIRES1DAY
0

One way of solving this problem without removing your default expiration set by mod_expires is to add a <Location> block for the URL that is being redirected. Let's say you're redirecting to a versioned folder and you will periodically change that version:

RewriteRule ^/approot/(.*)  /approot.1.2.3.4/$1 [R=307,L]

If you don't want that redirect to be cached (but you do want actual content to be cached), just add this block to your configuration:

<Location /approot>
    ExpiresActive Off
</Location>

Of course, "/approot" represents whatever URL you are redirecting.

Simple and easy. You don't have to fiddle with your already-working mod_expires configuration. You don't have to try to add or remove headers with mod_headers. You just tell mod_expires to not add its headers for the URL that you're redirecting.

I first tried the accepted answer above (by Francois Marier) but it didn't work because I didn't want to disable my ExpiresDefault setting and then have to replicate an expiration in many different areas of the configuration in its place.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .