While redirecting HTTP to HTTPS via .htaccess or server configurations is common, it has two significant drawbacks:
# Typical .htaccess redirect (what we want to avoid)
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
First, it creates an unnecessary extra request cycle. Second (and more critically), the initial HTTP request exposes users to potential MITM attacks during the redirect process.
HTTP Strict Transport Security (HSTS)
The most effective solution is implementing HSTS with preloading:
# Nginx configuration
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
# Apache configuration
Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"
Once set, browsers will automatically convert all HTTP links to HTTPS before making requests. For maximum security, submit your site to the HSTS preload list maintained by Chrome and adopted by other browsers.
Server-Side Enforcement
Configure your web server to only accept HTTPS connections:
Nginx Example
server {
listen 443 ssl;
server_name example.com;
# SSL configuration here
# Reject HTTP requests completely
if ($scheme != "https") {
return 444; # Close connection without response
}
}
Apache Example
<VirtualHost *:443>
ServerName example.com
# SSL configuration here
# Deny HTTP access
<If "%{HTTPS} != 'on'">
Require all denied
</If>
</VirtualHost>
For applications where server configuration isn't possible:
JavaScript Redirect (As Last Resort)
// Place in <head> before any content
if (window.location.protocol !== 'https:') {
window.location.href = 'https:' + window.location.href.substring(window.location.protocol.length);
}
Content Security Policy
Enforce HTTPS for all resources:
Content-Security-Policy: upgrade-insecure-requests
Consider DNS CAA records to enforce HTTPS certificates:
example.com. IN CAA 0 issue "letsencrypt.org"
example.com. IN CAA 0 iodef "mailto:security@example.com"
Verify your configuration with these tools:
- SSL Labs Test: https://www.ssllabs.com/ssltest/
- HSTS Preload List Checker: https://hstspreload.org/
- Security Headers: https://securityheaders.com/
While HTTP-to-HTTPS redirects via .htaccess are commonly recommended, they present two significant drawbacks:
- Performance impact: Each redirect creates an additional round-trip before establishing the secure connection
- Security vulnerability: The initial HTTP request is still exposed before the redirect occurs
Here are three approaches to enforce HTTPS without relying on HTTP redirects:
1. HTTP Strict Transport Security (HSTS)
The most robust solution is implementing HSTS via response headers:
<IfModule mod_headers.c> Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" </IfModule>
After the first HTTPS visit, browsers will automatically convert all HTTP requests to HTTPS before sending them.
2. Server Configuration (Apache Example)
Configure your virtual host to only listen on HTTPS:
<VirtualHost *:443> ServerName example.com SSLEngine on SSLCertificateFile /path/to/cert.pem SSLCertificateKeyFile /path/to/privkey.pem SSLCertificateChainFile /path/to/chain.pem </VirtualHost>
Then disable HTTP entirely by either:
- Not defining any VirtualHost for port 80
- Closing port 80 at the firewall level
3. Frontend Implementation with Service Workers
For SPAs, you can intercept navigation requests:
// sw.js self.addEventListener('fetch', event => { if (event.request.url.startsWith('http://')) { const httpsUrl = event.request.url.replace('http://', 'https://') event.respondWith(fetch(httpsUrl)) } })
Modern browsers support using window.location.protocol
to detect and upgrade:
if (window.location.protocol !== 'https:') { window.location.href = 'https://' + window.location.host + window.location.pathname }
Combine this with a cookie to prevent redirect loops.
Consider these DNS configurations:
- CAA Records: Restrict which CAs can issue certs for your domain
- HTTPS DNS Records: Use SVCB or HTTPS RR records (emerging standard)
Verify your setup using these tools:
curl -I http://example.com
(should show no response or connection refused)- Qualys SSL Labs test
- SecurityHeaders.io scan