Page is a not externally linkable
g1smd - 12:03 pm on Feb 13, 2013 (gmt 0)
Consider this simple scenario:
RewriteCond %{QUERY_STRING} ^digits=([0-9]+)&letters=([a-z]+)$
RewriteRule ^(index\.php)?$ http://www.example.com/%1-%2? [R=301,L]
RewriteRule ^([0-9+])-([a-z]+) /index.php?digits=$1&letters=$2 [L]
The first rule redirects requests for example.com/index.php?digits=123&letters=abc or for example.com/?digits=123&letters=abc to www.example.com/123-abc
The browser then requests www.example.com/123-abc which is internally rewritten by the second rule to /index.php?digits=123&letters=abc
This internal request should then invoke the index.php file, pass the parameters to it and the PHP should then deliver the page of HTML and content.
Unfortunately, the internally rewritten pointer now matches the pattern in the redirecting rule and www.example.com/index.php?digits=123&letters=abc is exposed back out on to the web as a URL and the user is redirected again in a loop. The PHP file never gets invoked.
The redirecting rule should test that THE_REQUEST contained query string parameters. This stops the rule being invoked when the internal pointer has parameters as a result of a previous internal rewrite. In that case, the requested URL was www.example.com/123-abc without parameters.
The pattern for matching THE_REQUEST is necessarily more complex. It usually begins ^[A-Z]{3,9}\ / and often ends \ HTTP/ with various other stuff in the middle to match optional index.php, e.g. /(index\.php)? followed by parameters. Rather than use \?digits=[0-9]+&letters=[a-z]+ here, the parameters part can often be generalised to \?[^\ ]+ or similar.
REQUEST_URI is modified as a result of internal rewrites, THE_REQUEST is not.