.htaccess on Apache: how redirects, caching and security rules work
An .htaccess file is read by Apache on every request in the directory where it lives, which lets behavior change without restarting the server, and the mod_rewrite module is what interprets the redirect conditions and rules inside it.
Condition, rule, and the %{HTTPS} variable
Forcing HTTPS takes two lines: `RewriteCond %{HTTPS} off` tests whether the current connection is not secure, and the following `RewriteRule` redirects with a 301 (permanent) status to the same URL with the scheme switched to https. The `[L]` flag on the rule tells mod_rewrite to stop processing further rules after this one, keeping a second rule from rewriting the result again in the same pass.
Stripping the www uses a `RewriteCond` that matches `^www\.(.+)$` against the Host header, capturing everything after "www." into `%1`, and the following rule redirects to that captured value without the prefix. Adding the www does the reverse: it checks whether the Host does not start with "www." and, if it does not, prefixes it. The two rules never run active at the same time, since they would strip and add the www in an endless cycle.
The real trap shows up when Apache sits behind a reverse proxy or CDN that already terminates TLS before the request reaches it: in that case `%{HTTPS}` always reads "off" at the origin, even with the visitor connecting over https, and the force-HTTPS rule falls into an infinite redirect loop. The usual fix is to check the `%{HTTP:X-Forwarded-Proto}` header sent by the proxy instead of `%{HTTPS}` in that specific scenario.
Three rules, three effects
Force HTTPS enabled
Input
forceHttps: true
Expected output
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The 301 status signals a permanent redirect to browsers and tells Googlebot to index the https version as canonical.
The [NC] flag makes the host comparison case-insensitive, so "WWW.site.com" also matches the condition.
Image caching
Input
browserCaching: true
Expected output
ExpiresByType image/png "access plus 1 year"
CSS and JavaScript get only a 1-month cache, and HTML pages get "access plus 0 seconds" so they never get stuck in browser cache.
Full tool FAQ
In the site's root folder (usually public_html or www) or the specific directory you want to configure. The rules apply to that directory and its subdirectories. The file name is exactly .htaccess, with a leading dot and no extension.
Frequently asked questions
Why does my HTTPS redirect enter an infinite loop?
The most common symptom is Apache sitting behind a reverse proxy or CDN that already delivers the connection as HTTP to the origin after terminating TLS at the edge. Since `%{HTTPS}` always reads "off" in that case, the rule redirects endlessly; the test needs to use `%{HTTP:X-Forwarded-Proto}` instead of `%{HTTPS}`.
What is the difference between a 301 and 302 redirect in .htaccess?
301 is permanent and tells browsers and search engines to update the saved link and transfer SEO value to the new URL; 302 is temporary and keeps the old URL as the primary reference, useful for maintenance or tests that should revert later.
What does the [L] flag do on a RewriteRule?
It tells mod_rewrite to stop applying further rules once this one matches, within the current processing pass. Without it, a later rule could rewrite an already-handled URL again, producing a different result than intended.
Do I need mod_headers for the security headers to work?
Yes: the `Header always set` directives sit inside an `<IfModule mod_headers.c>` block, so if that module is not enabled in Apache, the whole block is silently ignored instead of raising a visible error.