Forum Moderators: phranque

Message Too Old, No Replies

Multiple RewriteCond RewriteRule

Applying multiple rewriterules depending on folder/files exisitng

         

dave_c00

2:54 pm on Jan 13, 2012 (gmt 0)

10+ Year Member



Hi,

I have sivved through the forums and still cannot seem to get the correct structure for my htaccess file.

What I currently do is the following:

RewriteRule ^section/(.*)/(.*)/$ section.php?id=$1 [QSA,L]

but now I want to apply the following RewriteRule and if the file cannot be found use the old rewrite rule (above).

RewriteRule ^section/(.*)/(.*)/$ static/sections/c$1.html [QSA,L]

Any help would be greatly appreciated.

Dave

g1smd

8:21 pm on Jan 13, 2012 (gmt 0)

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



The (.*) subpattern means "match everything". After "everything" there's a slash, so it has to "back up and retry" to "find" it. After the slash is another "everything". This is a promiscuous, greedy and ambiguous pattern that eats vast amounts of processor cycles. Change the pattern.

With both of your rules you don't check the $2 value and that allows infinite duplicate content on your site.

lucy24

10:19 pm on Jan 13, 2012 (gmt 0)

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



but now I want to apply the following RewriteRule and if the file cannot be found use the old rewrite rule (above).

You mean you want to rewrite to a file that might not happen to exist?

Aaaaaaccck!

Nooooo!

g1 will come back presently and explain it in grownup terms.

lucy24

8:22 am on Jan 15, 2012 (gmt 0)

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



OK. I've calmed down.

When you say

RewriteRule ^section/(.*)/(.*)/$ section.php?id=$1 [QSA,L]

do you mean

RewriteRule ^section/([^/]+)/[^/]+/$ section.php?id=$1 [QSA,L]
(throwing away the second directory)

or do you mean
RewriteRule ^section/([^/]+/[^/]+)/$ section.php?id=$1 [QSA,L]
(capturing the two directories as a unit)

or do you mean
RewriteRule ^section/(([^/]+)/)+[^/]+/$ section.php?id=$1 [QSA,L]
(there might be any number of directories, of which you're capturing all but the last one)

or do you mean
RewriteRule ^section///$ section.php?id= [QSA,L]
(allowing for the possibility of no content other than the explicitly required directory slashes)

or do you mean something else entirely?

The fact that you're currently using the rule and it does what you want it to do strongly implies that all your requests involve exactly two directories, and the second of the two is purely for decoration since you don't use it in the capture.

What you're looking at now is something involving -f meaning "a file with this name exists". You have to check this before deploying the rule, because otherwise you end up with a cascade of 404s and infinite redirects.

This rule comes before your existing Rule. Anything that doesn't meet the conditions of the new Rule will carry on as usual to the old Rule.

You'll notice that I don't actually write out the new Rule and Condition. This is partly because it is good for your soul to hammer it out yourself, and partly because I tested it on myself and could not get it to work. Mysteriously it would sometimes work if I tried a !-f variation, so I know that my host doesn't speak some arcane dialect of Apache that simply doesn't recognize -f. The -f versions didn't result in any cascading errors, they just didn't do anything. :(

:: looking around vaguely for g1, who claims to be on vacation but is really just putting his feet up and catching up on some reading* ::


* Or, in the alternative, cleaning the garage and painting the bathroom. One does not like to inquire too deeply.

dave_c00

11:02 am on Jan 16, 2012 (gmt 0)

10+ Year Member



Thanks for your reply lucy24,

I am disregarding the second directory and in this case the first part is an integer so I now have the following RewriteRule:

RewriteRule ^section/([0-9]+)/[^/]+/$ category.php?id=$1 [QSA,L]

My reason for needing the RewriteCond though is that I am building static pages to help speed the site up. If however for some reason the requested static page doesn't exist, rather than throw a 404, I would like it to run the old dynamic page.

so my url would look like this:

http://www.example.com/section/13/foo-bar/

and my static page would be:

http://www.example.com/static/sections/c13.html

and my dynamic page would be:

http://www.example.com/category.php?id=13

As pointed out the following line should be used so that if the requested file cannot be found run another RewriteRule.

RewriteCond %{REQUEST_FILENAME} !-f

So putting it all together I though the following might work:

RewriteRule ^section/([0-9]+)/[^/]+/$ static/sections/c$1.html [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^section/([0-9]+)/[^/]+/$ category.php?id=$1 [QSA,L]

It obviously works when the static page exists but when I delete it or rename it a 404 error is thrown.

g1smd

11:08 am on Jan 16, 2012 (gmt 0)

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



By disregarding the $2 part, you allow infinite duplicate content and also open up your site to allow malicious linking.

All parts of the requested URL should be evaluated and a non-valid URL should return 404.

dave_c00

11:34 am on Jan 16, 2012 (gmt 0)

10+ Year Member



Ok noted, the pages evalutate the page name as well now.

lucy24

5:15 pm on Jan 16, 2012 (gmt 0)

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



I hope that was a typo in your new version. The Condition goes with the first rule, so it has to come before it. (See various other threads for blather about mod_rewrite operating on a "two steps forward, one step back" principle.) This is also why they tell you to leave a blank space after each Rule.

You don't need QSA after the first page name. Queries are reappended by default unless your Rule has added a new one: then the default is to replace the query unless you put in the QSA.

Last time I looked, {REQUEST_FILENAME} referred to the incoming request: that is, what you've got before the Rule is applied. You need this to weed out bogus requests-- but then you also need something to look at what would be there after the Rule. So that gets you two different Conditions that both have to be met.