How to make Apache’s mod_rewrite redirect over HTTPS by default?
Solution 1
ServerName
accepts a scheme as well, e.g. ServerName https://example.com
. Changing this in the configuration and restarting Apache did the trick.
From the documentation:
Sometimes, the server runs behind a device that processes SSL, such as a reverse proxy, load balancer or SSL offload appliance. When this is the case, specify the
https://
scheme and the port number to which the clients connect in theServerName
directive to make sure that the server generates the correct self-referential URLs.
Solution 2
This is a way to do it:
RewriteEngine On
#redirect all your http trafic to https exept /foo & /bar
RewriteCond %{HTTP_HOST} ^example.com
RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_URI} !(/foo|/bar)
RewriteRule (.*) https://example.com$1 [R=301,L]
#redirect /foo trafic to /bar
RewriteCond %{HTTP_HOST} ^example.com
RewriteCond %{REQUEST_URI} /foo
RewriteRule /foo(.*) http://example.com/bar$1 [R=301,L]
Put this into your httpd.conf, or before all your virtual host, and it will be applied to all requests starting with example.com (www.example.com will not be redirected)
To apply the rule to all domains, you can remove the line RewriteCond %{HTTP_HOST} ^example.com
For information, you should avoid .htaccess usage if possible, to prevent useless hard disk access.
Related videos on Youtube
Mathias Bynens
I work on Chrome and web standards at Google. ♥ JavaScript, HTML, CSS, HTTP, performance, security, Bash, Unicode, macOS.
Updated on September 18, 2022Comments
-
Mathias Bynens over 1 year
Let’s say I have a website that is available over HTTPS, e.g.
https://example.com/foo
. Consider the following.htaccess
:RewriteBase / RewriteEngine On RewriteRule ^foo$ bar [R=301,L]
Now, when I visit
https://example.com/foo
, it redirects tohttp://example.com/bar
, over HTTP instead of HTTPS.How can I make it go to HTTPS other than using the full scheme + host for every
RewriteRule
with theR
flag? That is, this would do what I’m after:RewriteBase / RewriteEngine On RewriteRule ^foo$ https://example.com/bar [R=301,L]
However, my
.htaccess
file contains many suchRewriteRule
s, and it feels like there should be a way to tell Apache/mod_rewrite “rewrite tohttps://
by default”. What I’m really looking for is a directive to tell Apache the site is using HTTPS, similar to how one can declare the host name throughServerName foo.ext
. Is that possible?I guess this is a similar question on Stack Overflow: How to convince Apache of the original client protocol
-
kasperd over 8 yearsAre you using separate
VirtualHost
for HTTP and HTTPS? Or are you using the sameVirtualHost
for both protocols? -
kasperd over 8 yearsI have found it quite convenient to use one
VirtualHost
for HTTP that simply redirects everything to HTTPS (a very simple task, you don't need mod-rewrite for that). And a separateVirtualHost
that only serves HTTPS. I have no idea if such a separation helps with the specific issue you are asking about though. -
Mathias Bynens over 8 yearsThe
VirtualHost
is HTTP-only. HTTPS is taken care of by the load balancer in this particular case. What I’m really looking for is a directive to tell Apache the site is using HTTPS, similar to how one can declare the host name throughServerName foo.ext
. -
kasperd over 8 yearsThe question would be a lot clearer if you'd include that information in the question.
-
jcaron over 8 yearsIs Apache actually receiving anything as HTTPS, or does HTTPS always ends at the load balancer which then forwards to the web server as HTTP? Do you have any options in the load balancer to rewrite redirects?
-
Mathias Bynens over 8 yearsApache is dealing with HTTP only. That said, I have now put
ServerName https://example.com
in myhttpd.conf
and still the redirects go tohttp://
, so I doubt it depends on the ports it’s listening on.
-
-
Mathias Bynens over 8 yearsI’m really looking for a solution that doesn’t require the
!(/foo|/bar)
part. For a site with hundreds of redirects this doesn’t really scale. Is there no way to tell Apache the site is using HTTPS, similar to how one can declare the host name throughServerName foo.ext
? -
Froggiz over 8 yearsIf you add your full configuration it could be helpfull tu understand what you want to achieve. Cause what i wrote with flag L and placed in first position will be executed in first ignoring all other redirect... So i don't see the link with your hundreds of redirect.
-
Mathias Bynens over 8 yearsI have hundreds of redirects, so the
!(/foo|/bar)
list would become very long and unmaintainable. I’d prefer hardcoding the fullhttps://example.com/
for every single redirect (as in the example in my post) rather than having to tweak the regex every time a redirect is added, but even that solution isn’t ideal. So, I’m hoping there’s a better way. -
Froggiz over 8 yearsSorry i don't understand what you want to achieve, i can help you only with more explicit example. I hope you noticed that my solution is not for .htaccess but for apache .conf files so it only need to be wrote once.
-
Mathias Bynens over 8 yearsThis solves a different problem, i.e. redirecting from
http://
tohttps://
. I’ve got that covered already. My question is: how to make RewriteRule with relative destination URLs point tohttps://
rather thanhttp://
? -
Felix Jen over 8 yearsLooks like I completely misread your question. However, Rewrite can still work.
Rewrite /foo https://example.com/bar
should do what you are asking. -
Mathias Bynens over 8 yearsInteresting. My question is how
Rewrite /foo /bar
can be made to work as if it saidRewrite /foo https://example.com/bar
rather thanRewrite /foo http://example.com/bar
. -
Felix Jen over 8 yearsI would think that if you do
Rewrite / https://example.com/
as the first initial rewrite, then followed by the standardRewrite /foo /bar
, it would automatically take you to the HTTPS version. Is this not the case? I seem to have this working on my sites and subdirectories. Every subdirectory I visit is still an HTTPS connection. -
Nick almost 6 yearsI really hate such stupid comments but WOW! :)