Forum Moderators: phranque

Message Too Old, No Replies

Remove "index.php" only if no querystring

Conditional rewrite

         

grintoul

4:16 am on Mar 8, 2007 (gmt 0)

10+ Year Member



Hi everyone,

I'm trying to create a rule where if the url is http://www.example.com/index.php it redirects to [domain.com...] BUT if it has a querystring (e.g. http://www.example.com/index.php?variable=random) it leaves the URL as it is. I've come up with:

# Remove index.php
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/index.php$
RewriteCond %{QUERY_STRING} SOMETHING
RewriteRule ^(.*)index\.php$ /$1 [R=301,L]

I don't know what to put instead of SOMETHING to test whether there's a query string. Can anyone help? And apart from that, does this rule look correct - I'm new to this so gave it my best shot!

Thanks in advance,

Guy

[edited by: jdMorgan at 1:45 pm (utc) on Mar. 8, 2007]
[edit reason] example.com [/edit]

jdMorgan

2:04 pm on Mar 8, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Three problems:

First, you must use THE_REQUEST to examine only the original client (e.g. browser) request. Otherwise, if you use DirectoryIndex to map "/" to "/index.php", then the RewriteRule and DirectoryIndex directives will interact, and lead to an 'infinite' loop, as the RewriteRule redirects "/index.php" to "/" and DirectoryIndex rewrites "/" back to "/index.php" repeatedly.

Second, you must use a canonical URL in the RewriteRule substitution when doing external redirects, in order to avoid problems with the setting of the UseCanonicalName directive.

Third -- and your original question, the regular-expressions token for <something> is ".", meaning "any single character," or ".+" meaning, "one or more of any character." But because "HTTP/" follows the URL and query string in a browser request header, we can't use either here in an efficient manner, so this code looks for "one or more characters not equal to a space" instead:


RewriteEngine on
RewriteBase /
#
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^/]+/)*index\.php\?[^\ ]+\ HTTP/
RewriteRule ^(([^/]+/)*)index\.php$ http://www.example.com/$1 [R=301,L]

Note that the "(([^/]+/)*)" RewriteRule pattern means, "Match one or more characters not equal to a slash, followed by a slash, and as many of the preceding sequences as you like (including zero), and remember the whole thing, saving it as back-reference $1." This is more efficient than using "(.*)" because it allows a single-pass left-to-right string compare, instead of requiring multiple back-offs from the end-anchored pattern to get a match. The pattern in the RewriteCond is similar, except that there is no need to create an overall back-reference, so one layer of parentheses is omitted.

THE_REQUEST will look something like this for your example:

GET /optional_subdir/index.php?name1=value1&name2=value2 HTTP/1.1

This is the original request header sent by the client (e.g. browser or SE robot).

Jim