Skip to content

Add static asset caching and mod_expires to fpm-apache - #734

Open
twiesing wants to merge 1 commit into
serversideup:mainfrom
twiesing:apache-static-asset-caching
Open

twiesing wants to merge 1 commit into
serversideup:mainfrom
twiesing:apache-static-asset-caching

Conversation

@twiesing

@twiesing twiesing commented Oct 25, 2026 •

Copy link
Copy Markdown

Follow-up to #717. fpm-apache sends no cache headers for static files, and <IfModule mod_expires.c> blocks in .htaccess are skipped because expires is not enabled. fpm-nginx has had Cache-Control for assets since #487.

This enables mod_expires and adds a performance.conf, enabled by default like security.conf, with the same extensions and Cache-Control: public, max-age=31536000, immutable as fpm-nginx, plus Access-Control-Allow-Origin: * for fonts. The header is set with Header set … "expr=-z %{resp:Cache-Control}", so mod_expires rules and Header set or Header always set in .htaccess take precedence; setifempty only sees the onsuccess table and left two Cache-Control headers next to an always rule. <FilesMatch> matches the served file, so a missing asset rewritten to index.php gets no header from here, unlike nginx's try_files.

It also sets DeflateAlterETag Remove. mod_deflate's default -gzip ETag never matches in If-None-Match, so compressed responses were never revalidated with a 304. Without the ETag, browsers use If-Modified-Since and get one. NoChange would fix the 304 too, but gives gzip and identity one strong ETag, and a mixed If-Range request then gets a 206 cut from the gzip bytes.

One behaviour change: existing mod_expires blocks in apps' .htaccess files now take effect.

Tested on serversideup/php:8.5-fpm-apache (Apache 2.4.69) with the changed files layered on top: the headers for assets and fonts, precedence of ExpiresByType, Header set and Header always set in .htaccess, no header for 404s and rewritten requests, 304 for a gzip response with If-Modified-Since, /healthcheck unchanged, apache2ctl -t. ShellCheck, hadolint and scripts/tests/run.sh pass.

Fixes #735

Match fpm-nginx's performance.conf: Cache-Control for assets, media and fonts, set only when the response has none, and CORS for fonts. Enable mod_expires for .htaccess rules, and remove mod_deflate's -gzip ETag, which never matched in If-None-Match.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fpm-apache: compressed responses never get a 304 (mod_deflate's -gzip ETag)

1 participant