laur
laur

Reputation: 590

ExpiresByType & 'Header set Content-Type' race condition

ExpiresByType has no effect on assets whose mimetype gets set by Header set Content-Type rule.

Config:

<Directory /var/www/html>
  Options Indexes FollowSymLinks MultiViews
  Order allow,deny
  allow from all
  allowoverride none
  <FilesMatch "health$">
    Header set Content-Type "application/json"
  </FilesMatch>

  # enable expirations:
  ExpiresActive On
  ExpiresDefault "access plus 1 year"

  # expire json after shorter time:
  ExpiresByType application/json "access plus 1 minute"
</Directory>

All json files (by extension) get appropriate Cache-Control: max-age=60 header set, but all files matching health$ receive the default year (31536000) value. I would expect to get 1 minute expiry for those files as well, as previous rule sets their content-type to json.

Looks like there's some racing in the configuration, i.e. expiry rules get executed before header setting ones.

Upvotes: 0

Views: 258

Answers (1)

covener
covener

Reputation: 17871

There is no race here or even any kind of undefined ordering, the expiration stuff will always runs before "Header set" because of how the modules that do this work register with the core of Apache.

One thing to keep in mind that helps these kinds of investigations in Apache is that the configuration is read at startup and stored in the corresponding modules that will later be called during request processing. In other words, ordering in the config file of directives from different modules is usually meaningless. What's meaningful is when during the request processing a module springs to life, consults its configuration, and makes changes.

Both mod_headers and mod_expires run the work you're asking them to do relatively late, after the response has been generated. Why? Because they both make changes relative to other response headers.

If the question here were how to get some alternative behavior, it partially depends on what produces the response for the health checks (or whatever the special requests are).

  • If they are static files, you could simply use ForceType which would happen much earlier.
  • If they are dynamic in any way, early directives like ForceType or "Header early set" will unfortunately just be over-written by whatever dynamic thing thinks it knows a better Content-Type for what it's producing.

One potential simple option for dynamic files would be to use ExpiresDefault in the FilesMatch.

Upvotes: 1

Related Questions