Forum Moderators: phranque

Message Too Old, No Replies

Rewrite Rule generating 500 Server Error

         

posaune02

1:49 am on Apr 24, 2008 (gmt 0)

10+ Year Member



I have a rewrite rule that is causing a 500 server error. I've tested the regex at regextester.com and it works fine.

RewriteRule ^rewrite(/([a-zA-Z0-9]+)(/([a-zA-Z0-9]+))?)?(\.([a-zA-Z]+))?/?$ /rewrite.php?id=$2&num=$4&format=$6 [QSA]

This rewrite rule is the same as above but without the + sign on the last character set. This rule works fine.

RewriteRule ^rewrite(/([a-zA-Z0-9]+)(/([a-zA-Z0-9]+))?)?(\.([a-zA-Z]))?/?$ /rewrite.php?id=$2&num=$4&format=$6 [QSA]

Any suggestions?

jdMorgan

1:21 pm on Apr 24, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The main problem appears to be that in the first rule, the entire initial path-pattern is optional. Therefore, when you include the "+" on the final subpattern, then the pattern will match the initial "^rewrite", skip the optional subpattern, and then match the final "(\.([a-zA-Z]+))?/?" subpattern.

In short, an initial request for anything that matches the pattern will get rewritten to "rewrite.php". This rewritten URL will then also match, and get rewritten to "rewrite.php?id=&num=&format=php". This rewriting loop will then continue until the server gives up and generates a 500-Server Error.

Your pattern is too complex, contains too many "optional" parts, and is therefore behaving unexpectedly. In these cases, I suggest using more than one rule, with each one tailored to a specific (and simpler) case, rather than trying to write one complex rule that matches everything you want to rewrite, without matching anything you don't want to rewrite.

However, if you are satisfied that your current pattern is exactly what you want, excepting the looping case, then the problem can be solved by explicitly excluding "rewrite.php" itself from being rewritten, by adding a RewriteCond to your rule:


RewriteCond %{REQUEST_URI} !^/rewrite\.php$

When you get a 500-Server Error, your first step should be to examine your server error log -- It often contains specific information that is quite useful in finding the problem. No server error log? -- Time for a better host, then, if you want to use mod_rewrite, scripts, and other complex features.

Jim

posaune02

6:46 pm on Apr 24, 2008 (gmt 0)

10+ Year Member



Could there be an easier rule to accomplish the same thing? Preceding this rule in my .htaccess file is one that adds a trailing slash (301 redirect) to all requests that do not have a '.' in the last portion. so /test -> /test/ and /test/more -> /test/more/ but /test/more.html -> /test/more.html

The goal is to take an requests of the form /rewrite/id/num/ and rewrite to /rewrite.php?id=ID&num=NUM

Further, any extension would be added as ?format=EXT
Some examples:


/rewrite/ -> rewrite.php
/rewrite.rss -> rewrite.php?format=rss
/rewrite/ID/ -> rewrite.php?id=ID
/rewrite/ID.rss -> rewrite.php?id=ID&format=RSS
/rewrite/ID/NUM/ -> rewrite.php?id=ID&num=NUM
/rewrite/ID/NUM.rss -> rewrite.php?id=ID&num=NUM&format=rss

Non-trailing extensions can be ignored. I don't care if these are rewritten or not, whichever is easiest. eg.
/rewrite.rss/ID/NUM/ -> ?

jdMorgan

11:30 pm on Apr 24, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Simple is good:

RewriteRule ^rewrite/$ /rewrite.php [L]
RewriteRule ^rewrite/([a-zA-Z0-9]+)/$ /rewrite.php?id=$1 [QSA,L]
RewriteRule ^rewrite/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/$ /rewrite.php?id=$1&num=$2 [QSA,L]
#
RewriteCond $1 !^php$
RewriteRule ^rewrite\.([a-zA-Z]+)$ /rewrite.php?format=$1 [QSA,L]
RewriteRule ^rewrite/([a-zA-Z0-9]+)\.([a-zA-Z]+)$ /rewrite.php?id=$1&format=$2 [QSA,L]
RewriteRule ^rewrite/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)\.([a-zA-Z]+)$ /rewrite.php?id=$1&num=$2&format=$3 [QSA,L]

Note that [QSA] is not needed unless a new query string needs to be appended to the existing one; By default, query strings are passed through mod_rewrite unchanged. That's why I omitted it on the first rule.

At some point, you might consider passing *all* ^rewrite.+$ requests to your script, and let the script itself pull the parameters from the URL. Just remember that in either case, if the passed URL is not valid, the server or script should return a 404 or another error response, so as to avoid presenting search engines with an 'infinite URL space'.

Jim