I’ve been trying to figure this one out for a few days now and have finally made a simplified enough test environment so that I can post this question with several examples.
The problem I’m running into is that my htaccess file is ignoring both the <If>
and <Else>
conditions. I am using Apache version 2.4.29 which does support this feature. Likewise, when I save the htaccess file, I do not get a 500-level error– the site works just fine (besides these being ignored).
My use case is that I’d like to listen for a query parameter and change the Cache-Control header based on whether that query parameter exists. I’m sure others would disagree with this premise and while I’m curious what a better solution would be, I would like to get to the bottom of this particular issue.
I’ve tried feeding several conditions to the <If>
thinking that maybe it just didn’t like the format or that I was doing something wrong there, but I’ve now simplified it to be simply <If false>
to try to force the <Else>
side of the conditional. No matter what I do, neither side of the conditional is working– it is simply ignored completely.
Am I doing something wrong? I believe my syntax matches the documentation, but maybe I’m missing something… While I do have a lot of experience writing .htaccess files, I will admit I am far from an Apache expert.
Test cases
I made a webpage that simply loads a single image.png
file and I read the Cache-Control header in Chrome DevTools.
Example A
.htaccess file contents:
<FilesMatch "png">
Header set Cache-Control "max-age=123, public"
</FilesMatch>
<If false>
<FilesMatch "png">
Header unset Cache-Control
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
</FilesMatch>
</If>
<Else>
<FilesMatch "png">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>
</Else>
Expected: The Cache-Control
max-age
should be 31536000
Actual: The Cache-Control
max-age
is 123
Example B
.htaccess file contents:
<If false>
<FilesMatch "png">
Header unset Cache-Control
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
</FilesMatch>
</If>
<Else>
<FilesMatch "png">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>
</Else>
Expected: The Cache-Control
max-age
should be 31536000
Actual: No Cache-Control
header exists at all
Edit: A clue has emerged that I am able to use 301 RedirectMatch inside the If/Else conditions, so it seems like the cache control headers are what is being ignored from within the conditionals… If that is the case, I’m curious what other options I have to make my use case (described above) work.
Edit 2: Another clue is that without the <FilesMatch>
line, the Cache-Control max-age header is applied as expected (just not to the right files).
2
Answers
So I found a work-around for my specific use-case which is why I am "answering" my own question, but I am not "accepting" this answer as it does not resolve the core problem. I wanted to provide this for anyone who stumbles upon this issue in the future.
What I found was that
<FilesMatch>
was what was being ignored inside of<If>
and<Else>
conditions. Redirects and headers could be set without a problem within them.So for my use-case, I flipped the logic around. I set the regular cache lengths as I wanted for individual file types using
<FilesMatch>
(outside of any conditionals). Then, I added an<If>
condition to check for the query string, and if true it would unset all Cache-Control headers (so no FilesMatch as it was for all files).Here is an example of what I'm now doing for my work-around (in the same format as the above examples):
Again, this does not actually answer the core question, so I am not going to "accept" my own answer, but I wanted to provide it for anyone else.
You may be able to use
if/else
for.png
files like this:Expectedly it will set
Cache-Control: max-age=31536000, public
for all.png
files.