Forum Moderators: phranque

Message Too Old, No Replies

RewriteRule help - moving to Apache/ linux from windows

RewriteRule help

         

Filbert

12:23 pm on Feb 15, 2011 (gmt 0)

10+ Year Member



Hi All. any help with this will be much appreciated:

I'm looking for a mod_rewrite rule for the following scheme:

Visitor / supplied sample url:
*.php/param1/value1/param2/value/2/param3/value3/paramx/valuex

matching to:
whatever.php?value1=param1&param2=value2&param3=va lue3&paramx=valuex

I have been using isapi_rewrite on windows but am wanting to move over to linux / apache, I was previously using this rule:

RewriteEngine on
RewriteRule ^(.*?\.php)/([^/]*)/([^/]*)(/.+)? $1$4?$2=$3 [NC,LP,QSA]

But LP (Loop) is not an apache mod_rewrite flag and i can't work out how to use N or whatever to loop the rule and get the above output.

The main thing is that the number and name of params/values is unknown so it needs to replace all ? & = with /'s.

Thanks hopingly...

jdMorgan

11:26 pm on Feb 17, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Apache mod_rewrites's [N] flag would apparently be the equivalent to ISAPI Rewrite's [LP]. With some other re-coding for efficiency and portability, we'd get:

RewriteRule ^(([^/]+/)*[^.]+\.php)/([^/]+)/([^/]+)(/.+)?$ /$1$5?$3=$4 [QSA,N]

However, be aware that this re-starts mod_rewrite processing from the very top, and can therefore be *very* inefficient -- quite-visibly-slow to users. Also, mod_rewrite has a known bug that sometimes causes various parts of the server filepath to get re-injected unexpectedly into the output.

For these reasons, it is often better to enumerate all of the possible valid input URL-path "depths" and to write a rule for each one. Put these rules in order from most-often-requested-format to least, and just take the simple approach and do the whole rewrite within a single rule.

So, for example, for path-depths from two to six (one to three name/value pairs):

RewriteRule ^(([^/]+/)*[^.]+\.php)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)$ /$1?$3=$4&$5=$6&$7=$8 [L]
RewriteRule ^(([^/]+/)*[^.]+\.php)/([^/]+)/([^/]+)/([^/]+)/([^/]+)$ /$1?$3=$4&$5=$6 [L]
RewriteRule ^(([^/]+/)*[^.]+\.php)/([^/]+)/([^/]+)$ /$1?$3=$4 [L]

If more than three name/value pairs must be handled, use chained rules. Be aware that only $1 through $9 and %1 through %9 back-references are valid, so this establishes the maximum number of possible variables per rule.

If you have access to the .php code and can modify it, consider using AcceptPathInfo instead of doing a rewrite. Simply explained, AcceptPathInfo will check to see if /showcat.php/cat/10 exists as a physical file. If so, it will take no action, and that file will be directly invoked. If not, then it will check to see if /showcat.php/cat exists as a physical file. If so, it will invoke that file and pass it "/10" as a parameter on STDIN. If not, it will check to see if /showcat.php exists as a physical file, and if so, it will pass it /cat/10 on STDIN. If not, it will check to see if / exists as a physical file (it must resolve to a physical file defined by DirectoryIndex in this case), and if so, it will pass it /showcat.php/cat/10 on STDIN. If not, it will exit and a standard 404-Not Found response will be invoked.

Basically, AcceptPathInfo strips the requested URL-path back to the lowest-level (deepest) path that resolves to a physically-existing file, and then passes the remaining path-info to that file on STDIN. It is very useful for sites using your current URL format. All that is required is to modify the script to take its parameters from STDIN instead of reading the query string -- It basically looks like using the POST method instead of the GET method.

Jim

Filbert

12:40 pm on Feb 25, 2011 (gmt 0)

10+ Year Member



Massive thank you, that's exactly what I was after.