35

I want to redirect any traffic that goes to http://example.com to https://example.com

same for http://example.com/about to https://example.com/about

I thought it would be something like this:

RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
animuson
  • 53,861
  • 28
  • 137
  • 147
Brad
  • 12,054
  • 44
  • 118
  • 187
  • 1
    Please use example.com for all domain issues if you don't want to use your actual domain. – animuson Jul 13 '10 at 17:31
  • Possible duplicate of [How to redirect all HTTP requests to HTTPS](http://stackoverflow.com/questions/4083221/how-to-redirect-all-http-requests-to-https) – shellco Feb 11 '16 at 06:12

6 Answers6

76

This works for me:

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

If the traffic is coming in over non-SSL HTTP, then redirect to the HTTP equivalent of whatever page the user was originally trying to access. It also doesn't involve any mod_rewrite options, so it's easy to read.

Side rant: why does everyone feel the need to explicitly set the HTTP code of the redirect and mark one of their rewrites as the "last" one? Seriously, I've seen dozens of same-looking htaccess rules in just the last few days.

Borealid
  • 95,191
  • 9
  • 106
  • 122
  • 3
    I think if the rewrite is "corrective" action, the 301 response is probably more appropriate than the default 302 response, and it requires explicit declaration. As far as the `L` goes, it's unnecessary if you won't have any further rule matches, but if you do it could easily prevent the redirection by erasing the new scheme/host information. Considering that most people "forget" to post the rest of their ruleset half the time, it's the safer option. If there aren't any more rules though, I agree that it's just clutter, and I really don't get it when they use it on the only rule in the file... – Tim Stone Jul 13 '10 at 19:23
  • 2
    While this seems to work, it's wrong: that because this relies on the "Host" header, which is sent by the client. Furthermore, the host header could also contain the port: so if the host header in the client request contains the port :80, the Location will have the port :80, with https, which is wrong. See http://serverfault.com/questions/814153/apache-returning-wrong-location-header. The answer from t-richards http://stackoverflow.com/a/27930928/1504300 seems better – reallynice Nov 10 '16 at 09:12
  • @reallynice you could just hardcode the Host header as well, right? For servers where there is only one. Often you might not have access to server main configuration file, but you have .htaccess rights, so in those cases I'd just use this but hardcode the host. – eis Jan 15 '17 at 15:24
  • This is recommended against in the Apache official documentation, i.e. "When not to use mod_rewrite": https://httpd.apache.org/docs/2.4/rewrite/avoid.html and for this reason I also prefer the answer from t-richards – cazort Apr 21 '17 at 14:28
12

This is a previous answer using .httaccess but adding changes proposed in the comments, and some from me:

RewriteEngine on
RewriteBase /
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://my.domain.name%{REQUEST_URI} [L,R=301]

Notes:

  • This is for the cases where user doesn't have access to main configuration, but has access to .htaccess rules. If you have access to main configuration, use mod_alias solution instead.
  • For me the rule was not picked up without defining RewriteBase. Explicitly defining it gets rid of ambiguity with some server setups.
  • At least on some configurations, %{HTTPS} is not set to off when using http, but is null, so !on is more reliable rule than off.
  • For explicit host name, you don't rely on client side Host header or server configuration. However, explicit host name natually assumes there is only one domain to redirect. Host header poses some considerable problems, such as containing port and being client-supplied data. Another alternative, as suggested by Apache Wiki, is to use %{SERVER_NAME}. If you consider using that, check out caveat from this discussion - it relies on other configuration being correct.
  • R=301 means it's permanent redirect, as it's usually meant to be in this case. If you instead think it's temporary, that can be left out or specified as R=302.
  • L means it's last rule to be applied for this request. Leave it if you suspect or know there are other rules after this that you don't want to get applied. You can remove if this is the only rule of the file.
eis
  • 51,991
  • 13
  • 150
  • 199
8

According to the Apache documentation, using mod_alias is more appropriate than mod_rewrite for this task. That is, in order to redirect all HTTP traffic to HTTPS, one would:

<VirtualHost *:80>
    ServerName www.example.com
    Redirect permanent / https://www.example.com/
</VirtualHost >

<VirtualHost *:443>
    ServerName www.example.com
    # ... SSL configuration goes here
</VirtualHost >

Two things to note about this configuration:

  1. You need access to the main server configuration file in order for this configuration to work. The VirtualHost directive is only valid in the "server config" context.
  2. Keep in mind that mod_rewrite directives are processed before mod_alias directives. If you've already got a massive block of RewriteRules in your .htaccess file, you might be better off with the mod_rewrite configuration.
t-richards
  • 225
  • 3
  • 11
  • 1
    In my case the "Redirect permanent" had to be: `Redirect permanent http://www.example.com https://www.example.com` otherwise at browser I get a loop error – Andrés Chandía May 12 '17 at 10:11
3

why not just plain and simple?

rewriteCond %{HTTPS} !on
rewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

it has worked to me, and seems to me clear. Cheers.

Andres Felipe
  • 4,292
  • 1
  • 24
  • 41
  • My preferred approach also, works nicely to push to repos as often devs have sites set up on different vhosts. – user25794 Jul 04 '18 at 11:03
1

Working in all conditions is:

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [NE,L,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,L,R=301] 

<IfModule>
Raghbendra Nayak
  • 1,606
  • 3
  • 22
  • 47
0

After some research this what worked for me, a bit different version.

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]