When working with Apache's mod_rewrite in .htaccess files, %{HTTP_HOST}
and %{HTTPS}
(often mistaken as HTTPS_HOST) serve fundamentally different purposes:
# HTTP_HOST matches the domain name regardless of protocol
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
# HTTPS is a flag (on/off) indicating SSL usage
RewriteCond %{HTTPS} off
Contrary to some documentation, there is no actual HTTPS_HOST
variable in Apache. What developers typically encounter is either:
- Confusion between
%{HTTPS}
(the SSL flag) andHTTP_HOST
- Custom variables set by server configurations
Here's how to properly implement protocol-specific rules:
# Force HTTPS for all requests
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Handle specific HTTP-only cases
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^api\.example\.com$ [NC]
RewriteRule ^(.*)$ http://cdn.example.com/$1 [L,P]
For complex routing scenarios, combine protocol checks with host matching:
# Different behavior for HTTP/HTTPS on same domain
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^shop\.example\.com$ [NC]
RewriteRule ^cart$ /secure-cart [L]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^shop\.example\.com$ [NC]
RewriteRule ^cart$ /unsecured-cart [L]
When troubleshooting, log both values:
RewriteLogLevel 3
RewriteLog /path/to/rewrite.log
RewriteCond %{HTTPS} ^(on|off)$
RewriteRule ^ - [E=PROTOCOL:%{HTTPS},E=HOST:%{HTTP_HOST}]
Remember that protocol handling should always be tested with various combinations:
- http://example.com
- https://example.com
- http://www.example.com
- https://subdomain.example.com
In Apache's mod_rewrite environment, HTTP_HOST
and HTTPS_HOST
serve fundamentally different purposes:
# HTTP_HOST contains the hostname from the request (protocol-agnostic)
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
# HTTPS_HOST is a boolean flag (1/0 or on/off) indicating SSL usage
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Many developers assume these variables work similarly, but they don't:
- HTTP_HOST: Contains the requested hostname (e.g., "www.example.com") regardless of protocol
- HTTPS (not HTTPS_HOST): Boolean indicating if SSL is being used
Case 1: Force HTTPS for Specific Domains
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
Case 2: Protocol-Specific Redirects
# Redirect HTTP traffic for specific paths
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/secure-path
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Environment Detection
# Set environment variable based on protocol
RewriteCond %{HTTPS} on
RewriteRule ^ - [E=PROTO:https]
RewriteCond %{HTTPS} off
RewriteRule ^ - [E=PROTO:http]
Load-Balanced Environments
# Handle X-Forwarded-Proto headers in cloud environments
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
To verify your rules are working:
# Create a test endpoint
RewriteRule ^test-protocol$ - [E=INFO:https=%{HTTPS},host=%{HTTP_HOST}]
Header set X-Protocol-Info "%{INFO}e" env=INFO
When working with these conditions:
- Place protocol checks early in your ruleset
- Combine multiple conditions where possible
- Avoid redundant checks for the same protocol