Forum Moderators: phranque

Message Too Old, No Replies

Rewrite rule, what am I missing here?

Not sure how this could possibly work

         

Mike521

2:37 pm on Aug 24, 2012 (gmt 0)

10+ Year Member



I've had this working fine in my htaccess:

RewriteCond %{REQUEST_URI} ^/p/(.*)[NC]
RewriteRule (.*) /php/pages.php?type=product&code=%1 [QSA,L]

We recently set it up so all customers who log in will do so securely, so after logging in they're looking at an https page. I don't want my product pages to be secure, so I tried adding a rewrite like so:

RewriteCond %{server_port} =443
RewriteCond %{REQUEST_URI} ^/p/(.*) [NC]
RewriteRule (.*) http://example.com/p/%1 [R=301]
RewriteCond %{REQUEST_URI} ^/p/(.*)[NC]
RewriteRule (.*) /php/pages.php?type=product&code=%1 [QSA,L]

This looks to me like it should work, but it doesn't - the user is not redirected to a non-secure page, instead they remain on the https page (which loads fine). The strange thing is, if I add an L to the secure rewrite, both rewrites work correctly. How can that possibly be if they're both trying to be the last rewrite? Shouldn't one of them screw up the other?

RewriteCond %{server_port} =443
RewriteCond %{REQUEST_URI} ^/p/(.*) [NC]
RewriteRule (.*) http://example.com/p/%1 [R=301,L]
RewriteCond %{REQUEST_URI} ^/p/(.*)[NC]
RewriteRule (.*) /php/pages.php?type=product&code=%1 [QSA,L]

Even though this works I don't want to go live with it since I don't understand it. We're on Apache version 2.2.18.

Anyone know what's going on, and/or how I can improve it?

g1smd

2:48 pm on Aug 24, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



[L] means stop here if this rule matched.

There's no need to use REQUEST_URI as a condition. Just use that pattern as the main RewriteRule pattern in place of the (.*) one and use $1 instead of %1.

You should also add a mirror image ruleset redirecting from http to https for all pages that should be viewed as https.

It is vital to ensure that every page can only be viewed one way and that the incorrect way is always redirected.

Add a blank line after every RewriteRule so you have a chance to see the code more clearly.

lucy24

4:32 pm on Aug 24, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The strange thing is, if I add an L to the secure rewrite, both rewrites work correctly. How can that possibly be if they're both trying to be the last rewrite? Shouldn't one of them screw up the other?

You've misunderstood the [L] flag. If it meant "This is my last Rule" there would be no point to the flag. Obviously there is always one final RewriteRule and then you go on to the next module. It doesn't mean "RewriteEngine Off" or similar.

It means "If this rule executes, then stop right here. Otherwise, try the next Rule." Almost all RewriteRules come with an [L] flag. That includes Redirects; the [L] isn't automatic the way it is with [F] or [G]. I have never personally met a Redirect that was not accompanied by an [L], but they must exist or the flag would be built in.

Mike521

8:12 pm on Aug 24, 2012 (gmt 0)

10+ Year Member



Thanks g1smd and lucy, I think I'm understanding. So you mean it's possible to have something like

RewriteCond <some sort of condition>
RewriteRule <some rule that might run, maybe cause of it's own condition> [L]
RewriteRule <another rule that will run only if the above rule fails>

I never realized that, I always thought once you hit a rule, it stopped at that rule whether it ran or not

that's a good idea about forcing URLs that should be secure to also redirect to https, I didn't think of that

also, about not needing the request URI, I thought so too but for some reason this doesn't work:

RewriteCond %{server_port} =443
RewriteRule ^/p/(.*) http://example.com/p/$1 [R=301,L]

but this does:

RewriteCond %{server_port} =443
RewriteCond %{REQUEST_URI} ^/p/(.*) [NC]
RewriteRule (.*) http://example.com/p/%1 [R=301,L]

Mike521

8:19 pm on Aug 24, 2012 (gmt 0)

10+ Year Member



I just found a less complicated example of needing the request URI. This works:

RewriteCond %{server_port} =443
RewriteCond %{REQUEST_URI} ^/info/ [NC]
RewriteRule (.*) http://example.com/info/ [R=301,L]

But this doesn't:

RewriteCond %{server_port} =443
RewriteRule ^/info/ http://example.com/info/ [NC,R=301,L]

g1smd

9:06 pm on Aug 24, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The RegEx pattern for REQUEST_URI should begin with a slash. This value is the actual request from the browser.

The RegEx pattern for RewriteRule must NOT begin with a slash. This value is localised on a "per directory" basis, stripped of all part parts and trailing slash above the current directory.

Mike521

1:58 pm on Aug 27, 2012 (gmt 0)

10+ Year Member



got it, that worked perfectly, thanks again!

g1smd

6:39 pm on Aug 27, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Also don't forget that a RewriteCond applies only to the next RewriteRule in the file.

Place a blank line after every RewriteRule to make this more clear.

Mike521

1:36 pm on Aug 28, 2012 (gmt 0)

10+ Year Member



yep I went through and spaced everything out to make it more readable. I wonder if I can get dreamweaver to do some syntax highlighting here : )