How to make Apache’s mod_rewrite redirect over HTTPS by default?

7,578

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 the ServerName 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.

Share:
7,578

Related videos on Youtube

Mathias Bynens
Author by

Mathias Bynens

I work on Chrome and web standards at Google. ♥ JavaScript, HTML, CSS, HTTP, performance, security, Bash, Unicode, macOS.

Updated on September 18, 2022

Comments

  • Mathias Bynens
    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 to http://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 the R 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 such RewriteRules, and it feels like there should be a way to tell Apache/mod_rewrite “rewrite to https:// 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 through ServerName 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
      kasperd over 8 years
      Are you using separate VirtualHost for HTTP and HTTPS? Or are you using the same VirtualHost for both protocols?
    • kasperd
      kasperd over 8 years
      I 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 separate VirtualHost that only serves HTTPS. I have no idea if such a separation helps with the specific issue you are asking about though.
    • Mathias Bynens
      Mathias Bynens over 8 years
      The 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 through ServerName foo.ext.
    • kasperd
      kasperd over 8 years
      The question would be a lot clearer if you'd include that information in the question.
    • jcaron
      jcaron over 8 years
      Is 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
      Mathias Bynens over 8 years
      Apache is dealing with HTTP only. That said, I have now put ServerName https://example.com in my httpd.conf and still the redirects go to http://, so I doubt it depends on the ports it’s listening on.
  • Mathias Bynens
    Mathias Bynens over 8 years
    I’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 through ServerName foo.ext?
  • Froggiz
    Froggiz over 8 years
    If 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
    Mathias Bynens over 8 years
    I have hundreds of redirects, so the !(/foo|/bar) list would become very long and unmaintainable. I’d prefer hardcoding the full https://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
    Froggiz over 8 years
    Sorry 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
    Mathias Bynens over 8 years
    This solves a different problem, i.e. redirecting from http:// to https://. I’ve got that covered already. My question is: how to make RewriteRule with relative destination URLs point to https:// rather than http://?
  • Felix Jen
    Felix Jen over 8 years
    Looks 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
    Mathias Bynens over 8 years
    Interesting. My question is how Rewrite /foo /bar can be made to work as if it said Rewrite /foo https://example.com/bar rather than Rewrite /foo http://example.com/bar.
  • Felix Jen
    Felix Jen over 8 years
    I would think that if you do Rewrite / https://example.com/ as the first initial rewrite, then followed by the standard Rewrite /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
    Nick almost 6 years
    I really hate such stupid comments but WOW! :)