Forum Moderators: phranque

Message Too Old, No Replies

One rewriterule not executing

         

nsanford

8:45 pm on Feb 1, 2010 (gmt 0)

10+ Year Member



Hi all,
Can anyone tell me what could be wrong with the following .htaccess code?
The first two rewrites work fine, but it doesn't execute the "specials.php?page=" rule.

TIA!
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php

RewriteRule ^([A-Za-z0-9_-]+)/?$ index.php?page=$1 [NC]
RewriteRule ^([a-zA-Z0-9_-]+)/?$ specials.php?page=$1 [NC,L]

jdMorgan

9:23 pm on Feb 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That's because the new rules are more-specific than your first rule, and therefore, the first rule 'grabs' any requests that might otherwise invoke the 2nd and 3rd rule.

Put your most-specific rules first.

Note that using [A-Za-z] and the [NC] flag on a rule is redundant. You may remove [A-Z] if you use [NC].

Each rule should have an [L] flag.

The fist rule will be safer if coded as

RewriteRule ^(.+)$ /$1.php [L]

to prevent the client being able to control the initial path-part.

Jim

nsanford

9:32 pm on Feb 1, 2010 (gmt 0)

10+ Year Member



Hi Jim
Thank you for your response!
I changed the code to the following, but now it doesn't execute the index.php?page rule correctly. Every index.php?page is showing up as the main specials.php page.

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ /$1.php [L]
RewriteRule ^([a-zA-Z0-9_-]+)/?$ specials.php?page=$1 [L]
RewriteRule ^([A-Za-z0-9_-]+)/?$ index.php?page=$1 [L]

jdMorgan

11:07 pm on Feb 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You implemented part of what I said, but missed the most important. The rule order was incorrect:

RewriteRule ^([a-z0-9_\-]+)/?$ specials.php?page=$1 [NC,L]
RewriteRule ^([a-z0-9_\-]+)/?$ index.php?page=$1 [NC,L]
#
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ /$1.php [L]

Now look at those first two rules. The patterns are identical, so any requested URL that might match the second rule's pattern and invoke a rewrite to index.php will have already matched the first rule's pattern and will have been rewritten to "specials.php."

This is not a problem of coding, but rather of URL-design: There is no way that the same 'kind' of requested URL can trigger two different rules.

So, you will have to come up with 'something different' about the URLs to be rewritten to index.php compared to the URLs to be rewritten to specials.php -- You cannot rewrite identical-kind URLs to two different scripts.

Jim

g1smd

12:47 am on Feb 2, 2010 (gmt 0)

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



,,

nsanford

3:39 am on Feb 2, 2010 (gmt 0)

10+ Year Member



Thank you for the great explanation, Jim! I changed:

RewriteRule ^([a-z0-9_\-]+)/?$ specials.php?page=$1 [NC,L]

to:

RewriteRule ^specials-([a-z0-9_\-]+)/?$ specials.php?page=$1 [NC,L]

and it works!

Thanks again :)

g1smd

7:23 am on Feb 2, 2010 (gmt 0)

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



RewriteRule ^specials-([a-z0-9_\-]+)[b]/?[/b]$ specials.php?page=$1 [NC,L]


There are two flaws still to fix.

Add a slash to the start of the target filepath so that requests cannot inject their own server filepath.

This rewrite accepts URL requests both with and without a trailing slash. That's a Duplicate Content issue.

Change the rewrite to accept only requests without a trailing slash.

RewriteRule ^specials-([a-z0-9_\-]+[b])$[/b] [b]/[/b]specials.php?page=$1 [NC,L]


You will also need to add a completely new redirect, one that removes the trailing slash for those requests. It will also need to force or remove www in the same request. This new rule goes ahead of the rewrite, and ahead of any general canonicalisation rules.


There is potentially a third problem. The [NC] flag potentially allows more Duplicate Content, as a URL in aNy Case will show content. You should pick one exact casing as your canonical form (all lower case is preferred). Your script should examine the request and if any of it is in the 'wrong' case, the script should send a 301 redirect to the correct URL.

Finally, you need a redirect such that any direct client requests for a URL with
specials.php?page=
in it are redirected to your new URL format. You'll need one redirect for each such form. The redirect should also force or remove the www at the same time within the same redirect for those requests.