Forum Moderators: phranque

Message Too Old, No Replies

301 redirect when using ReWrites

strange things happening

         

BenSeb

6:23 pm on Dec 15, 2005 (gmt 0)

10+ Year Member



Hi

I'm using an htaccess file to rewrite some URLs. I recently changed the format of these so need to use a 301 redirect to direct from the old SEO friendly address to the new.

Something not quite right tho....

eg: OLD LINK:

RewriteRule ^product/category/(.*)/(.*)/$ mytown/index.php?c=$1&d=$2 [L]

NEW LINK (illustrative):

RewriteRule ^product-category/(.*)/(.*)/$ mytown/index.php?c=$1&d=$2 [L]

So I've added this:

RedirectRule 301 ^/product/category/(.*)/(.*)/$ http://www.example.com/product-category/(.*)/(.*)/

But when i do this, it redirects to:
http://www.example.com/product-category/(.*)/(.*)/?c=$1&d=$2

any ideas?

[edited by: pageoneresults at 6:29 pm (utc) on Dec. 15, 2005]
[edit reason] Examplified URI References [/edit]

jdMorgan

1:01 am on Dec 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes, the problem is that you are redirecting *after* rewriting to your script. In .htaccess, mod_rewrite behaves recursively, since the server must re-process all rules after any rewrite changes a URL in order to check the new URL against any other rewrites or access-control restrictions. The [L] flag only operates to terminate processing within the current pass, so the code must be carefully written to avoid recursion and infinite loops.

You can overcome your current difficulty by using only mod_rewrite, instead of using a mixture of mod_rewrite and mod_alias, so that you can enforce the execution order. Here's the full suite of rules needed to handle old-style URL redirects, non-canonical domain requests, static-to-dynamic rewrites, and the correction of "accidentally-exposed" dynamic URLs in the proper order:


# Externally redirect old-style static URLs to new style static URLs
RewriteRule ^product/category/([^/]+)/([^/]+)/?$ http://www.example.com/product-category/$1/$2/ [R=301,L]
#
# Externally redirect requests for non-canonical domain names
RewriteCond %{HTTP_HOST} !^www\.example\.com
RewriteRule (.*) http://www.example.com/$1 [R=301,L]
#
# Internally rewrite new-style static URLs to script
RewriteRule ^product-category/([^/]+)/([^/]+)/?$ /mytown/index.php?c=$1&d=$2 [L]
#
# Externally redirect direct client requests for dynamic URLs to new-style static URLs
# (in case your dynamic URLs accidentally get exposed to the search engines)
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /mytown/index\.php\?c=([^&]+)&d=([^&\ ]+)\ HTTP/
RewriteRule ^mytown/index\.php$ http://www.example.com/product-category/%1/%2? [R=301,L]

The code above eliminates the ".*" patterns, which are maximally-ambiguous and "greedy" patterns, and therefore much less efficient than the more-specific patterns shown. It also makes the trailing slash on the static URLs optional, so you won't have problems if a search engine drops them (like Yahoo has been doing lately).

An example of {THE_REQUEST} would be:


GET /mytown/index.php?c=widgets&d=14 HTTP/1.1

(it is the HTTP request header exactly as sent by the client browser or robot). We use {THE_REQUEST} to test the exact request sent by the client, so that this rule can't be fooled by the previous static-to-dynamic URL rewrite, and won't end up in a 'deadly embrace' with it, causing an 'infinite' loop.

I assumed that your /mytown directory is directly below document_root. If it is not, then either provide a full anchored path for the rewrites, or remove the leading slash from the rewrite substitution URLs.

Jim