# Utterly baffling Apache rewrite rule problem



## Terry_Kennedy (Jul 16, 2013)

I have the following three rewrite rules in my /usr/local/etc/apache22/extra/httpd-vhosts.conf file:
	
	



```
# Rule 1 - rewrite any example.com to www.example.com
    rewriteCond %{HTTP_HOST} ^example\.com
    rewriteRule (.*) http://www.example.com$1 [R=301,L]

    # Rule 2 - likewise for an IP literal.
    rewriteCond %{HTTP_HOST} ^10\.20\.30\.40
    rewriteRule (.*) http://www.example.com$1 [R=301,L]

    # Rule 3 - As rule 1, but for https
    # For some reason, this does not work.
    rewriteCond {HTTPS} =on
    rewriteCond %{HTTP_HOST} ^example\.com
    rewriteRule (.*) https://www.example.com$1 [R=301,L]
```
Both rule 1 and rule 2 work fine. Rule 3 acts like it is being completely ignored. I added the following to my site's main index.shtml page:
	
	



```
<!--#echo var="HTTP_HOST" -->
<!--#echo var="HTTPS" -->
```
and I correctly see "example.com on" (without the quotes) when I browse to https://example.com. But the rewrite rule, which should be triggered by those two matches, does not fire. Rearranging things so that rule 3 is first doesn't help, either.


----------



## ShelLuser (Jul 16, 2013)

What happens if you use:


```
RewriteCond %{SERVER_PORT} =443
```
I think that might be a better way to pick up if HTTPS is being used or not.


----------



## Terry_Kennedy (Jul 16, 2013)

ShelLuser said:
			
		

> What happens if you use:
> 
> 
> ```
> ...


I had tried that previously, but I just tried it again and the same thing happens (the URL is not rewritten). I then tried using this pair of rewrite rules:
	
	



```
rewriteCond {HTTPS} !=on
    rewriteCond %{HTTP_HOST} ^example\.com
    rewriteRule (.*) http://www.example.com$1 [R=301,L]

    # For some reason, this does not work.
    rewriteCond {HTTPS} =on
    rewriteCond %{HTTP_HOST} ^example\.com
    rewriteRule (.*) https://www.example.com$1 [R=301,L]
```
The first rule continues to function normally, even with the added check to make sure HTTPS is off. The second rule is still apparently ignored. Nothing of interest is logged in any of the /var/log/httpd-*.log files.


----------



## ShelLuser (Jul 16, 2013)

Your second example really doesn't prove anything because if HTTPS isn't set at all (which is what I'm assuming is happening here) then the first rule would still be executed.

I'm tempted to blame it entirely on the HTTPS variable because this isn't set by the core system but one of the plugins (I don't know from mind which). SERVER_PORT on the other hand is, so you can be sure it will be picked up.

Still, I know there are several scenario's where it's advised not to use mod_redirect, and some of these scenario's involve HTTPS.

So when all else fails I'd recommend using a name based virtual host which redirects visitors to the right one.


----------



## Chris_H (Jul 17, 2013)

Greetings,

 I have about 50 entries as below (one after the other) for those domains I want to direct to _only_ the primary DNS entry -- SomeDomain.com.

```
RewriteCond %{HTTP_HOST} ^HotBabes.NET [NC]
RewriteRule ^(.*)$ http://HotBabes.COM$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.HotBabes.NET [NC]
RewriteRule ^(.*)$ http://HotBabes.COM$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^HotBabes.ORG [NC]
RewriteRule ^(.*)$ http://HotBabes.COM$1 [L,R=301]
```
Several reasons I do this, but one most everyone should be interested in: Google will penalize you, if you have the the same content at www _and_ the dot com. While that's not my primary reason for doing it, I've discovered most people aren't aware, so I thought I'd share it.

_So_, if it's not apparent; everything above points to HotBabes.COM (my real domains have been omitted, to protect the innoce... guilty).  I used this _working_ example, which should make the logic trivial to reverse, for your needs -- http://www.SomeDomain.com.

HTH

--chris


----------



## Terry_Kennedy (Jul 17, 2013)

ShelLuser said:
			
		

> Your second example really doesn't prove anything because if HTTPS isn't set at all (which is what I'm assuming is happening here) then the first rule would still be executed.
> 
> I'm tempted to blame it entirely on the HTTPS variable because this isn't set by the core system but one of the plugins (I don't know from mind which). SERVER_PORT on the other hand is, so you can be sure it will be picked up.


Please take a look at my original post where I confirmed (by printing the environment variables in a web page) that both HTTP_HOST and HTTPS were being set properly. It's just that the rewrite isn't being triggered for some reason.



> So when all else fails I'd recommend using a name based virtual host which redirects visitors to the right one.


As I said in my original post, the rewrite from http://example.com to http://www.example.com is working fine. It's only when https:// is used that this doesn't work.



			
				Chris_H said:
			
		

> Greetings,
> I have about 50 entries as below (one after the other) for those domains I want to direct to _only_ the Primary DNS entry -- SomeDomain.com.


As I replied to the other poster, I'm already doing that. It's the specific case of getting the https:// version to work that's the problem.


----------



## ShelLuser (Jul 17, 2013)

Terry_Kennedy said:
			
		

> Please take a look at my original post where I confirmed (by printing the environment variables in a web page) that both HTTP_HOST and HTTPS were being set properly. It's just that the rewrite isn't being triggered for some reason.


I think I solved it, can't believe we all overlooked the obvious!

I did just as you asked, and suddenly it hit me:


```
# Rule 3 - As rule 1, but for https
    # For some reason, this does not work.
    rewriteCond {HTTPS} =on
    rewriteCond %{HTTP_HOST} ^example\.com
    rewriteRule (.*) https://www.example.com$1 [R=301,L]
```
Notice: {HTTPS} _instead of_ %{HTTPS}?

That has to be it.


----------



## Terry_Kennedy (Jul 17, 2013)

ShelLuser said:
			
		

> I think I solved it, can't believe we all overlooked the obvious!
> 
> I did just as you asked, and suddenly it hit me:
> Notice: {HTTPS} _instead of_ %{HTTPS}?
> ...


According to the Apache Httpd Wiki, they're interchangable when performing simple comparisons of equality/inequality between the variable and the item being tested against. In fact, the Wiki says that the %-less version is to be preferred for both performance and clarity reasons. Of course, if you need a regex, you have to do it the old way.

And adding the % doesn't change the behavior. None of these work:


RewriteCond %{SERVER_PORT} ^443$
rewriteCond %{HTTPS} ^on$
rewriteCond %{HTTPS} =on
rewriteCond {HTTPS} =on
Thanks for everybody's suggestions, though - I'm sure there's an explanation waiting to be discovered.


----------



## kpa (Jul 17, 2013)

Hmm I recall that certain types of rewrites do not work with HTTPS because the redirection looks at the HTTP headers and they are not available until the stream gets decrypted. Could it be something like that in this case?


----------



## ShelLuser (Jul 17, 2013)

kpa said:
			
		

> Could it be something like that in this case?


I think so. The article which I mentioned above states several scenario's when one should not use mod_rewrite but redirections instead, and several involve HTTPS.

So it might well be related to why you also can't use name based virtual hosts with HTTPS enabled websites.


----------



## Chris_H (Jul 17, 2013)

Greetings @Terry_Kennedy.

First I'd like to take a moment to apologize for not having taken the time to read your post _twice_, before responding -- I should know better, by now. 

Now, to my question. Given that order is everything, regarding re-write rules: do you have a separate section, there-by segregating HTTP from HTTPS? Or is it your intent to simply re-direct based on host _and_ protocol within the same rewrite block. I'm curious, because no context was necessarily given in your OP, and it makes a difference.

--chris


----------



## Terry_Kennedy (Jul 17, 2013)

ShelLuser said:
			
		

> I think so. The article which I mentioned above states several scenario's when one should not use mod_rewrite but redirections instead, and several involve HTTPS.


I looked at that article, but it specifically says that that the thing being matched by the redirect directive is a URL-path, not a URL. So it can't be used as a selector for http:// vs. https://



			
				Chris_H said:
			
		

> Greetings @Terry_Kennedy.
> First I'd like to take a moment to apologize for not having taken the time to read your post _twice_, before responding -- I should know better, by now.
> Now, to my question; Given that order is everything, regarding re-write rules; do you have a separate section, there-by segregating HTTP from HTTPS? Or is it your intent to simply re-direct based on host _and_ protocol within the same rewrite block. I'm curious, because no context was necessarily given in your OP, and it makes a difference.



This is an IP-based virtual host with the canonical URL http://www.example.com. The purpose of the three rewrite rules (which are independent of each other, as only one can be triggered by any request, though they're all in the same place in the config file) are:

Rule 1: Redirect http://example.com to http://www.example.com (working)
Rule 2: Redirect http://10.20.30.40 to http://www.example.com (working)
Rule 3: Redirect https://example.com to https://www.example.com (not working)

However, your response had me look through the configuration files again, and it appears I made an error when converting the single monolithic /usr/local/etc/apache2/httpd.conf file of Apache 2.0 to the multiple /usr/local/etc/apache22/extra/httpd-*.conf files of Apache 2.2. The rewrite rule landed in the wrong file and was not being processed in SSL mode. All better now. Thanks for the pointer!


----------

