Forum Moderators: phranque

Message Too Old, No Replies

Rewrite rule causing loop.

         

seti

9:19 am on Mar 23, 2010 (gmt 0)

10+ Year Member



Hi everyone,

I have a virtual host config file. My website works on both 80 and 443 protocols. In config file added following code in appropriate VirtualHost directives, which is causing a loop.

<VirtualHost *:80>
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} (user|admin)
RewriteRule ^/(.*)$ https://example.com/$1 [R=301,L]
</VirtualHost>

<VirtualHost _default_:443>
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !=(user|admin)
RewriteRule ^/(.*)$ http://example.com/$1 [R=301,L]
</VirtualHost>


How to do this schema working?
If there are strings "user" or "admin" and request was done using 80th port in the url then redirect to 443 port.
If else, the port is 443 and there are NO such strings as "user" or "admin" then redirect to 80-port.

Any answers are highly appreciated!

jdMorgan

12:39 pm on Mar 23, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The %{HTTPS} variable is not an Apache core variable. A more-portable solution is to check %{SERVER_PORT} for port 80 or port 443 -- or for "not port 80" or "not port 443."

Also, you're requiring an *exact* match on "not /user" or "not /admin," meaning that directory and file paths below these directories will not be matched -- They will always be redirected by the second rule.

In addition, the URL-path in the Request_URI variable always starts with a slash, and a RewriteCond should not be used to test the URL-path unless the RewriteRule cannot be used to do this.

Finally, since the rules are already scoped to http and https by their locations within the vHost containers, checking %{HTTPS} or %{SERVER_PORT} is probably not even necessary.

Most likely, correcting the second problem will fix your code, and the other inefficiencies can be removed as well:

<VirtualHost *:80>
RewriteRule ^/((user|admin)(/.*)?)$ https://example.com/$1 [R=301,L]
</VirtualHost>

<VirtualHost _default_:443>
RewriteCond $1 !^(user|admin)(/.*)?$
RewriteRule ^/(.*)$ http://example.com/$1 [R=301,L]
</VirtualHost>

[added] Alternative format for second rule -- I'm not sure, but it might be faster:
 <VirtualHost _default_:443>
RewriteRule !^/(user|admin)(/.*)?$ http://example.com%{REQUEST_URI} [R=301,L]
</VirtualHost>
[/added]

Jim

seti

4:52 pm on Mar 23, 2010 (gmt 0)

10+ Year Member



Thank you Jim for your reply!
It seems that first rule doesn't work.
<VirtualHost *:80> 
RewriteRule ^/((user|admin)(/.*)?)$ https://example.com/$1 [R=301,L]
</VirtualHost>


I tried to apply my rule but it is still looping. Also, I want this rule apply not only this kind of url: http://example.com/user but also http://example.com/somepathsbefore/user/andafter

Additionally, I tried to change your regex to this
^((/.*)(user|admin)(/.*))$
but again, loop. Any other ideas?

jdMorgan

5:33 pm on Mar 23, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The code I posted should have done what you want. Note that $1 refers to the entire contents of the first set of parentheses, which encloses the entire URL-path.

Do not use ".*" as an initial subpattern, and do not use it at all when a more-specific pattern is usable. Doing so can result in very-inefficient processing, because it matches "anything, everything, and nothing." This can lead to dozens, hundreds, or even thousands of "back off and retry" matching attempts. So use specific patterns...

Fire up "Live HTTP Headers" (or a similar HTTP headers checker) and see where the 'extra' redirect is coming in... I'm fairly certain you'll find one that is *not* being done by this code. And if not, then the redirection-sequence info will still be very useful.

Jim

seti

11:49 am on Mar 24, 2010 (gmt 0)

10+ Year Member



Hi Jim,

Continuing to struggle with redirections.
I tried to apply only your this first rule:
RewriteRule ^/((user|admin)(/.*)?)$ [example.com...] [R=301,L]

Browser is not reacting to your rule at all. I think here I have to do something but I don't know what.

Tried also my first rule and your second rule like shown here:

<VirtualHost *:80>
RewriteCond %{REQUEST_URI} (user|admin)
RewriteRule ^/(.*)$ [example.com...] [R=301,L]
</VirtualHost>

<VirtualHost _default_:443>
RewriteCond $1 !^(user|admin)(/.*)?$
RewriteRule ^/(.*)$ http://example.com/$1 [R=301,L]
</VirtualHost>

Received following headers:
HTTP/1.1 301 Moved Permanently =>
Date => Wed, 24 Mar 2010 11:34:51 GMT
Server => Apache/2.2.12 (Ubuntu)

Is this tells you something? Thank you for your efforts!

jdMorgan

1:01 pm on Mar 26, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The header report is not at all useful without the requested URL-path and the redirected-to URL returned by the server in the HTTP "Location" header.

Check all the URL-path patterns in the code to be sure they are complete and correct. If one single character is missing or incorrect, the pattern will not match, and the rule will not be invoked.

Jim