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

RewriteEngine On # Force HTTPS RewriteCond %{HTTPS} off RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # Force www RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

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 set X-Frame-Options "SAMEORIGIN" Header set Cache-Control "public, max-age=3600" Header unset X-Powered-By

Header adds, replaces, or removes headers on the response going back to the clientset 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 vs. RequestHeader — two directives that sound the same
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

<IfModule mod_deflate.c> AddOutputFilterByType DEFLATE text/html text/plain text/css application/javascript application/json SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|zip|gz|mp4)$ no-gzip DeflateCompressionLevel 6 </IfModule>

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.

ModuleKey directiveAllowOverride group
mod_rewriteRewriteRule / RewriteCondFileInfo
mod_headersHeaderFileInfo
mod_deflateAddOutputFilterByTypeFileInfo
Why FileInfo is such a heavily-used AllowOverride group
All three modules in this chapter share the exact same 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

Exercise 1

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 solution
Exercise 2

A 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 solution
Exercise 3

Explain, 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 solution

Chapter 4 Quick Reference

  • mod_rewriteRewriteCond gates a RewriteRule; [L] stops further rules, [R=301] sends a real external redirect instead of an internal rewrite
  • mod_headersHeader touches 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 with SetEnvIfNoCase ... no-gzip; Apache's own counterpart to Nginx's gzip
  • All three modules' directives fall under the same AllowOverride FileInfo group from Chapter 3