Apache: Set global headers only if not already set

apache-2.2conditional

I am having a little annoying situation here.

I have a server managed by plesk.
In the /etc/apache2/apache2.conf mod_headers and mod_expires based configuration takes place.
For example:

<filesMatch "\.(jpg|jpeg|png|gif|swf)$">
    Header set Cache-Control "max-age=604800, public"
</filesMatch>

This is working quite well.

I have a problem with some of my applications. I want to application to keep the control over cache if it wants to.
Currently this is not possible, because header settings takes place emediatly before returning the response to the client, which means after the application has completeted all their actions. The headers set by the application will be overwritten.

Header merge Cache-Controll...

is not working though, because it just appends the given header string. And I doubt that browsers would handle headers like this one like I would like them to:

Cache-Control max-age=0, no-cache, no-store, must-revalidate, max-age=604800, public

My question now is: Is there a possibilty to set the header only if there is absolutly no content in the specific header "field"?
I do not want my application to set any enviroment variables, because an application should not be changed to fit the needs of one server.

I also tried – for testing purpose only – to unset the header via vhost.conf for a specific domain. But it gets executed before the header setting in the apache2.conf, which means they would be overwritten, too.

Best Answer

I think you can pull this off using Header edit. The secret sauce is a negated look-ahead assertion:

Header edit Cache-control "^(?!.*max-age.*)(.*)" "max-age=604800,\1"

The idea is that the ^(?!.*max-age.*)(.*) matches the start of the header value if the string max-age does not exist anywhere in the header. If the match succeeds (meaning "max-age" does not already exist) it then inserts "max-age=604800," followed by the rest of the original header.

EDIT: Apache uses PCRE, so you might need to use $1 instead of \1 in the replacement string.