Forum Moderators: phranque

Message Too Old, No Replies

URL rewrite catch-all

I hope I am just missing something simple

         

EricaC

2:21 am on Jun 11, 2007 (gmt 0)

10+ Year Member



This is somewhat related to this post:
[webmasterworld.com...]

The simplist way to present this is that I have one dynamic page

http://example.com/shop

I dont care what comes after the "shop", trailing slash or not, "/shop/category/12/", whatever, it all gets dealt with in a shop.php file.

All other requests I wish to be processed by a different script.

Here's what I've gotten to work so far...

Attempt 1:
RewriteEngine on
RewriteCond %{REQUEST_URI} /shop
RewriteCond %{REQUEST_FILENAME}!-f
RewriteCond %{REQUEST_FILENAME}!-d
RewriteRule .* /shop.php
RewriteCond %{REQUEST_URI}!/shop
RewriteCond %{REQUEST_FILENAME}!-f
RewriteCond %{REQUEST_FILENAME}!-d
RewriteRule .* /process.php

This does work as expected. except the fact that I have to hide all files I dont wish to be served up directly in subdirectories. If I try to remove the REQUEST_FILENAME lines (which seems logically what I wish to do), I get 500 errors.

Attempt 2:
RewriteEngine on
RewriteCond %{REQUEST_URI}!/shop
RewriteRule ^([^\.]+)$ /process.php [L]
RewriteCond %{REQUEST_URI} /shop
RewriteRule ^([^\.]+)$ /shop.php

This works, but if someone puts in something with a . in the url, they get a 404. not what I'm looking for, I want a true catch-all.

Is there some explanation as to why those REQUEST_FILENAME conditions are necessary? Am I missing something else?

Thanks in advance!

jdMorgan

4:17 am on Jun 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The reason your found the "file exists" and "directory exists" checks to be necessary is that they prevent an infinite rewrite loop. This is because your scripts exist, and the other URLs don't. But "exists" checks are very expensive in terms of CPU, and this overhead should indeed be eliminated if possible.

So, having got rid of the "exists" checks, you just need to check that you have not already rewritten the request before you rewrite it. The problem with the URLs containing a "." was just a regex pattern error. Once that is addressed, a bit of optimization can then be accomplished by getting rid of the original redundant REQUEST_URI checks and moving them into the RewriteRule pattern.


RewriteEngine on
#
RewriteCond %{REQUEST_URI} !/process\.php$
RewriteRule !^shop /process.php [L]
#
RewriteCond %{REQUEST_URI} !/shop\.php$
RewriteRule ^shop /shop.php [L]

In both cases, the RewriteCond now prevents an 'infinite rewrite loop' and the test for the URLs you do want to rewrite has been moved into the rule itself.

Jim

EricaC

6:01 pm on Jun 11, 2007 (gmt 0)

10+ Year Member



Ok - now I'm getting somewhere! Thank you so much for the help :)

Just one quick follow up...

If I want to add another (or possibly a few more) exceptions to this code, is this the most efficient way to go about it?
(this code does work, just curious about optimization).

RewriteEngine On
#
RewriteCond %{REQUEST_URI}!process\.php$
RewriteRule!^(shop¦test) /process.php [L]
#
RewriteCond %{REQUEST_URI}!/shop\.php
RewriteRule ^shop /shop.php [L]
#
RewriteCond %{REQUEST_URI}!/test\.php
RewriteRule ^test /test.php [L]

jdMorgan

1:48 am on Jun 12, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, that should work, but once you start adding a bunch of scripts, the mutual-exclusion problem starts to get out of hand.

You might be happier with just:


RewriteEngine on
#
# Rewrite "shop" urls to shop.php
RewriteCond %{REQUEST_URI} !/shop\.php$
RewriteRule ^shop /shop.php [L]
#
# Rewrite "test" urls to test.php
RewriteCond %{REQUEST_URI} !/test\.php$
RewriteRule ^test /test.php [L]
#
# Rewrite all others to process.php
RewriteRule !\.php$ /process.php [L]

Or alternately:

RewriteEngine on
#
# Rewrite "shop" and "test" urls to php script
RewriteCond %{REQUEST_URI} !\.php$
RewriteRule ^(shop¦test) /$1.php [L]
#
# Rewrite all others to process.php
RewriteRule !\.php$ /process.php [L]

There are many ways to do this. Think about your current and future needs, and try to pick a method that will grow with your needs and be easy to maintain and to understand.

Replace the broken pipe "¦" characters above with solid pipes before use; Posting on this forum, modifies the pipe characters.

Jim