Forum Moderators: phranque

Message Too Old, No Replies

Multiple RewriteCond on one line

so I can retain two variables

         

Mike521

9:38 pm on Aug 13, 2012 (gmt 0)

10+ Year Member



I would like to do something like this:

RewriteCond %{REQUEST_URI} ^/dir/([A-Za-z0-9-_]+)/
RewriteCond %{QUERY_STRING} ^show=([0-9]+)
#RewriteRule ^(.*)$ http://www.example.com/dir/$1/?v2Show=$2 [QSA,R=301]

I read jdMorgan's info here and saw that this is impossible: [webmasterworld.com...]

However, there did seem to be a way to combine the two conditions into one line so you could get two variables out of it, but it's not working for me. Here's what I have, it seems to me like it's exactly the same as what jd wrote but I can't get it to match on the URL I'm using:

#RewriteCond %{REQUEST_URI}<>%{QUERY_STRING} ^show=([0-9]+)<>^/dir/([A-Za-z0-9-_]+)/
#RewriteRule ^(.*)$ http://www.example.com/dir/$1/?v2Show=$2 [QSA,R=301]

I feel like I'm close but must be missing something, can anyone help out?

lucy24

10:44 pm on Aug 13, 2012 (gmt 0)

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



Be careful reading jdmorgan's posts. He knows more about Apache than everyone else here combined-- BUT most of his information dates back to Apache 1.3. I really, really hope that's not what you are using. Most people are on 2.2, and the cutting-edge types have probably long since moved up to 2.4.

In this case it doesn't matter because the rule is the same. (I detoured to test. The wording of the respective pages is the same, but it's always good to buttress it with the evidence of your senses if possible.)

The bad news is that I couldn't get his version to work either. I tried some other garbage strings in place of "<>" to make sure it wasn't a string-specific problem. No 500-class errors; it just didn't do anything.

The good news in your case is that you don't need two Conditions, because the first one can and should be moved down into the Rule. Always make the Rule as restrictive at possible so the server doesn't have to check Conditions unless there's a pretty good chance the Rule will apply. So, here, your Rule would simply be (with a bit of editing) -- omit leading slash in htaccess, keep it in config file --

RewriteCond %{QUERY_STRING} \bshow=([0-9]+)
RewriteRule ^(dir/[^./]+)/ http://www.example.com/$1/?v2Show=%1 [QSA,R=301]

Leave out the opening anchor ^ in the Condition, unless the parameter "show" really does have to come at the beginning of the query. I replaced it with \b in case you have other parameters named, uh, "noshow" or "showushow" or what have you. Probably not necessary.

phranque

3:25 am on Aug 14, 2012 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



^show=([0-9]+)<>^/dir/([A-Za-z0-9-_]+)/


the problem is you only want to use the start anchor once in the regular expression and you inserted a 2nd "start anchor" within the regular expression after the fictitious "<>" string.

g1smd

6:54 am on Aug 14, 2012 (gmt 0)

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



You also have %{REQUEST_URI} and %{QUERY_STRING} data transposed.

I'd put the %{REQUEST_URI} data first.

lucy24

9:03 am on Aug 14, 2012 (gmt 0)

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



the problem is you only want to use the start anchor once in the regular expression and you inserted a 2nd "start anchor" within the regular expression after the fictitious "<>" string.

The variant I tried had no anchors at all.

Can either of youse get jdmorgan's code to work? What Apache version are you on?

Paradoxically I'm a little worried that my non-working attempts didn't get a 500 error. It implies that something was happening, but it ended up yielding a null result. And no way of tracking what that "something" was.

g1smd

9:58 am on Aug 14, 2012 (gmt 0)

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



#RewriteCond %{REQUEST_URI}<>%{QUERY_STRING} ^show=([0-9]+)<>^/dir/([A-Za-z0-9-_]+)/

You also have %{REQUEST_URI} and %{QUERY_STRING} data transposed.

I'd put the %{REQUEST_URI} data first.

phranque

9:59 am on Aug 14, 2012 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month




#RewriteCond %{REQUEST_URI}<>%{QUERY_STRING} ^show=([0-9]+)<>^/dir/([A-Za-z0-9-_]+)/
#RewriteRule ^(.*)$ http://www.example.com/dir/$1/?v2Show=$2 [QSA,R=301]

i didn't notice this before but you are using $1 and $2 for backreferences and should be using %1 and %2 since those are the backreferences to the captured groups in the RewriteCond.

Can either of youse get jdmorgan's code to work?

i got something similar to this working:

RewriteCond %{REQUEST_URI}<>%{QUERY_STRING} ^/dir/([A-Za-z0-9-_]+)/<>show=([0-9]+)
RewriteRule ^(.*)$ http://www.example.com/%1/?v2Show=%2 [R=301,L]


a request for:
http://www.example.com/dir/test/?show=8
redirects to:
http://www.example.com/test/?v2Show=8

not sure you want the QSA flag unless you want to get redirected to this instead:
http://www.example.com/test/?v2Show=8&show=8

What Apache version are you on?

this was tested on ...
Server version: Apache/2.2.6 (Unix)

g1smd

10:04 am on Aug 14, 2012 (gmt 0)

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



I didn't notice this before but you are using $1 and $2 for backreferences and should be using %1 and %2

I didn't notice that either. So, three errors: the caret, transposed data, and $ instead of %.

phranque

10:06 am on Aug 14, 2012 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



i'm also assuming the comments were removed when testing...

Mike521

1:52 pm on Aug 14, 2012 (gmt 0)

10+ Year Member



thanks everyone! I got one of the rewrites working based on the info you all supplied. Also, I checked our apache version, it's 2.2.15.

First, lucy24's solution worked but had a redirect loop:
RewriteCond %{QUERY_STRING} \bshow=([0-9]+)
RewriteRule ^(dir/[^./]+)/ http://www.example.com/$1/?v2Show=%1 [QSA,R=301]

I have to include any additional query string parameters, which is why I put the QSA. But this ended up turning into a redirect loop, I ended up at a page like ?v2Show=1&v2Show=1&v2Show=1.... I tried removing the \b but it still had a loop

I wanted to see if the original version would work if I applied the fixes everyone suggested, and it did, here's what I came up with:

RewriteCond %{REQUEST_URI}<>%{QUERY_STRING} ^/dir/([A-Za-z0-9-_]+)<>show=([0-9]+)
RewriteRule ^(.*)$ http://www.example.com/dir/%1/?v2Show=%2 [QSA,R=301]

thanks again for all the help!

Mike521

2:45 pm on Aug 14, 2012 (gmt 0)

10+ Year Member



I was actually able to fix lucy24's version by adding a line at the beginning:

RewriteCond %{QUERY_STRING} !v2Show=([0-9]+)

lucy24

7:48 pm on Aug 14, 2012 (gmt 0)

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



Urk. Has this site gone live yet? It might be safer not to have overlapping query strings like "show" and "v2Show". Especially if there's a chance your server won't pay attention to casing.

Did you explain at some point why the REQUEST_URI has to be in the Condition instead of in the Rule?

In the minimalist version I used for experimenting, the last part of the condition was simply (stringone)<>(stringtwo). This may have been too minimalist.

But this has been a phenomenally useful question because I never realized-- in spite of having read Apache's words probably dozens of times-- that when they say "last matched condition" they really mean it. So the only time a %1 back-reference in the Rule can refer to anything other than the very last Condition is when the Conditions end with an [OR]-delimited group of lines. Those work by sudden death,* so the capture would always be from the first one to match.


* Apache says so-- not in those exact words-- but I also tested it.

Mike521

6:20 pm on Aug 15, 2012 (gmt 0)

10+ Year Member



I agree, I ended up switching the 'v2Show' to something different, it wasn't a big deal to change it and I wanted to avoid those types of conflicts

I guess the request URI can be in the rule too, doesn't matter to me as long as it works. I'm just not very good with htaccess stuff so usually 'whatever works first' is what I go with : )

g1smd

6:40 pm on Aug 15, 2012 (gmt 0)

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



Make sure you test with valid and non-valid URLs to make sure that all produce the correct response.