When dealing with HTTPS requests, the server completes the SSL handshake before processing .htaccess rules. This fundamental difference from HTTP can cause rules to fail silently. The SSL layer wraps the entire request cycle, which means rewrite conditions may evaluate differently.
# Critical check for HTTPS context
RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The certificate validation process through Let's Encrypt or other CA providers often conflicts with rewrite rules. Special handling is required for ACME challenges during SSL renewal.
RewriteEngine On
# Handle HTTP->HTTPS first
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Then process PHP extension stripping
RewriteCond %{THE_REQUEST} \s/+(.*?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,NE,L]
# Final internal routing
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?id=$1 [L,QSA]
These server-level settings often override .htaccess:
- SSLProxyEngine interfering with internal rewrites
- HTTP/2 prioritization changing request order
- Mod_security rules blocking rewritten URLs
Enable verbose logging in your virtual host:
LogLevel alert rewrite:trace6
ErrorLog /path/to/ssl_rewrite.log
Check for these specific HTTPS rewrite pitfalls:
# Test if HTTPS is properly detected
RewriteCond %{SERVER_PORT} ^443$
RewriteRule ^ - [E=HTTPS:on]
# Alternative HTTPS detection
RewriteCond %{HTTP:X-Forwarded-Proto} https
RewriteRule ^ - [E=HTTPS:on]
When your .htaccess rules work in HTTP but fail in HTTPS, the first thing to check is your SSL configuration. The most common culprit is actually an incomplete SSL handshake. Unlike HTTP connections, HTTPS requires successful SSL negotiation before Apache processes .htaccess directives.
apache
# First verify SSL is properly configured
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/privkey.pem
SSLCertificateChainFile /path/to/chain.pem
Your current rules don't account for the HTTPS protocol. The RewriteCond
needs explicit handling of the HTTPS environment variable:
apache
RewriteEngine On
RewriteCond %{HTTPS} off
# For HTTP requests
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} on
# For HTTPS requests
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)\.php$ $1 [L]
RewriteRule ^(.*)$ index.php?id=$1 [L,QSA]
Enable rewrite logging to see exactly where the process breaks:
apache
RewriteLog "/path/to/rewrite.log"
RewriteLogLevel 3
Common HTTPS-specific issues to check:
- Mixed content warnings in browser console
- Certificate chain completeness
- Protocol-relative URLs in your application
Sometimes the issue stems from the SSL virtual host not inheriting the main configuration. Ensure both HTTP and HTTPS vhosts include:
apache
...
AllowOverride All
...
Here's a complete working example that handles both protocols:
apache
RewriteEngine On
# Force HTTPS first
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Then process other rules
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
RewriteRule ^(.*)\.php$ $1 [L]
RewriteRule ^(.*)$ index.php?id=$1 [L,QSA]