Core Modules: mod_rewrite, mod_headers & mod_deflate
Apache In Depth
Chapter 4 · Core Modules: mod_rewrite, mod_headers & mod_deflate
Web Servers Fundamentals never covered these three modules directly — the closest it came was Chapter 9's brief, comparative mention of compression across all three servers, and Chapter 3's FileInfo override group naming mod_rewrite in passing without explaining it. This chapter is genuinely new territory: real URL rewriting, real response-header control, and the actual Apache mechanism behind that compression Chapter 9 only gestured at.
mod_rewrite: RewriteCond and RewriteRule
A RewriteRule matches and rewrites the request URI; a RewriteCond immediately above it is a precondition that must be true first — multiple consecutive RewriteCond lines are combined with AND by default. %{HTTPS} and %{HTTP_HOST} are server variables mod_rewrite exposes, not literal strings. The [L] flag means "stop processing further rewrite rules if this one matches" (the same idea as Nginx's own ^~ prefix-match short-circuit from Nginx In Depth Chapter 3), and [R=301] sends an actual HTTP redirect back to the client rather than rewriting the URI silently — the exact same external-redirect-vs-internal-rewrite distinction Nginx's own rewrite ... permanent flag draws, just spelled differently.
mod_headers: Controlling Response Headers
Header adds, replaces, or removes headers on the response going back to the client — set replaces any existing value, add appends an additional header of the same name, unset removes it entirely. Common real uses: basic security headers like X-Frame-Options (full header-based hardening belongs to the site's own XSS and OWASP Top 10 courses, not this one), cache-control tuning for static assets, and stripping headers that leak server/framework details.
Header modifies the response Apache sends back to the client. RequestHeader — a separate directive, easy to reach for by mistake — modifies headers on the request Apache forwards to a backend, relevant specifically in a reverse-proxy setup (Chapter 7). Using Header when the actual goal is to inject or strip a header before it reaches a proxied backend does nothing useful — the client sees the change, the backend never does.
mod_deflate: Compressing Responses
AddOutputFilterByType applies gzip compression only to the listed MIME types — text-based content compresses well; binary formats that are already compressed don't. That's exactly what the SetEnvIfNoCase line guards against: it sets an environment variable mod_deflate itself checks, skipping compression entirely for URIs ending in an already-compressed extension. Running gzip against an already-compressed JPEG or ZIP file burns real CPU for little or no size reduction, and occasionally makes the file slightly larger. DeflateCompressionLevel (1–9, default 6) trades CPU time for compression ratio — this is Apache's own concrete mechanism behind the "compression" line Web Servers Fundamentals Chapter 9 only mentioned in passing, the direct counterpart to Nginx's gzip directive.
| Module | Key directive | AllowOverride group |
|---|---|---|
| mod_rewrite | RewriteRule / RewriteCond | FileInfo |
| mod_headers | Header | FileInfo |
| mod_deflate | AddOutputFilterByType | FileInfo |
AllowOverride group from Chapter 3: FileInfo. That's not a coincidence — FileInfo was specifically designed to cover directives that shape how a response is delivered (rewritten, headered, compressed) rather than directives touching authentication or raw filesystem access. A single AllowOverride FileInfo line is enough to permit everything in this entire chapter inside a .htaccess file, with none of Chapter 3's AuthConfig or Limit groups needed at all.
Hands-On Exercises
Write a mod_rewrite rule (RewriteCond + RewriteRule) that redirects any request to /old-blog/anything to https://example.com/blog/anything, preserving whatever came after /old-blog/, using a permanent external redirect rather than an internal rewrite.
📄 View solutionA developer wants to add a custom header to every request Apache forwards to a proxied backend application, so the backend can identify which Apache instance sent it. They write "Header set X-Proxy-Source apache1" in the config. Using this chapter's own warning box, explain why this won't achieve what they want, and what directive they should have used instead.
📄 View solutionExplain, in your own words, why applying mod_deflate's compression to a directory full of JPEG images would be a waste of CPU, and how the SetEnvIfNoCase line in this chapter's own mod_deflate example prevents it.
📄 View solutionChapter 4 Quick Reference
- mod_rewrite —
RewriteCondgates aRewriteRule;[L]stops further rules,[R=301]sends a real external redirect instead of an internal rewrite - mod_headers —
Headertouches the response to the client;RequestHeader(a separate directive) touches the request to a proxied backend - mod_deflate — compress by MIME type with
AddOutputFilterByType; skip already-compressed formats withSetEnvIfNoCase ... no-gzip; Apache's own counterpart to Nginx'sgzip - All three modules' directives fall under the same
AllowOverride FileInfogroup from Chapter 3