1

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

  • Are you using separate VirtualHost for HTTP and HTTPS? Or are you using the same VirtualHost for both protocols? – kasperd Jan 5 '16 at 15:36
  • @kasperd Right now it’s a single VirtualHost. – Mathias Bynens Jan 5 '16 at 15:48
  • 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. – kasperd Jan 5 '16 at 16:00
  • 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. – Mathias Bynens Jan 5 '16 at 23:17
  • The question would be a lot clearer if you'd include that information in the question. – kasperd Jan 5 '16 at 23:20
3

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.

  • I really hate such stupid comments but WOW! :) – Nick Jun 19 '18 at 13:56
1

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.

  • 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? – Mathias Bynens Jan 5 '16 at 23:15
  • 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. – Froggiz Jan 6 '16 at 9:18
  • 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. – Mathias Bynens Jan 6 '16 at 9:39
  • 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. – Froggiz Jan 6 '16 at 10:00
0

Is there any reason you are not using the plain Rewrite directive?

Rewrite / https://example.com/

For sub domains, you can do

Rewrite http://foo.example.com https://foo.example.com
  • 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://? – Mathias Bynens Jan 7 '16 at 18:46
  • Looks like I completely misread your question. However, Rewrite can still work. Rewrite /foo https://example.com/bar should do what you are asking. – Felix Jen Jan 8 '16 at 19:49
  • 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. – Mathias Bynens Jan 9 '16 at 22:59
  • 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. – Felix Jen Jan 10 '16 at 3:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.