Forum Moderators: phranque

Message Too Old, No Replies

Mod Rewrite Redirect Loop

         

jojy

10:00 pm on Jan 17, 2009 (gmt 0)

10+ Year Member



Hi,
I am trying to make my search engine url friendly.. I want to display urls like this

[site.com...]

I have written following htaccess but all it goes to loop..

RewriteRule ^search/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$ search.php?a=$1&b=$2 [NC,L] #if found match stop looking further

#this is the redirect code
RewriteCond %{QUERY_STRING} ^t\=([^&]+)\&s\=([^&]+)$
RewriteRule ^.*$ search/%1/%2? [R=301,NC,L]

I am using L flag to stop the htaccess on top but it doesn't work.. any help would be much appreciated.

Thanks

jdMorgan

11:11 pm on Jan 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



[L] stops mod_rewrite processing only for the current iteration through the mod_rewrite code: If any rewrites are invoked as a result of the initial mod_rewrite code execution, then processing is restarted from the top of the mod_rewrite code. So, mod_rewrite code should be seen as "re-entrant' and the [L] flag likely isn't doing what you expect.

In addition, an redirect rule sends a redirect response back to the client including the new redirection URL, and terminates the current HTTP transaction; It is then up to the client to start a new HTTP transaction, requesting the new URL returned by the server's previous redirect response. Since HTTP is a stateless protocol, the server sees this as an entirely new request, and the context of the previous request is not longer available.

In other words, the server has no idea if the current request it's working on is the result of a previous redirect or not; Each HTTP request exists on its own, and might be the first-ever or last-ever HTTP request that the server will ever handle for all it knows.

Therefore, [L] will not stop the kind of rewrite/redirect loop you have set up here.

The solution is to examine the HTTP request as sent by the client, and invoke the external redirect only if the "unfriendly" URL is requested by the client, and is not being requested as the result of the action of your internal rewrite rule:


# Internally rewrite SEO-friendly URL to script with query string
RewriteRule ^search/([a-z0-9_\-]+)/([a-z0-9_\-]+)$ search.php?t=$1&s=$2 [NC,L]
#
# Externally Redirect direct client requests for script URL back to SEO-friendly URL
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /search\.php\?t=([^&]+)\&s=([^&]+)[^\ ]*\ HTTP/
RewriteRule ^search\.php$ http://www.example.com/search/%1/%2? [R=301,L]

Note: DO NOT put comments on the same line as mod_rewrite directives. Although it is not a fatal error it is not allowed, and can fill your log file with "warnings" and slow down your server processing the warnings even if your LogLevel is set high enough so that they are not actually logged.

No need to include both "a-z" and "A-Z" in a RewriteCond or RewriteRule pattern if you've used the [NC] flag.

The code for the redirect looks a bit redundant, but it isn't; It specifically detects direct client requests for the script URL. Since the pattern is a bit complex, here's an example of a client request that it would match:

GET /script.php?t=foo&s=bar HTTP/1.1

This is the client request line, exactly as it appears in your raw server access logs.

Jim