Forum Moderators: phranque

Message Too Old, No Replies

Simple RedirectMatch 301 not working

         

benni_203

7:09 pm on Jun 6, 2009 (gmt 0)

10+ Year Member



I can't get a simple RedirectMatch 301 within the same page working. The basic redirect without "?id=3" works:

RedirectMatch 301 site.html$ /newpage/1.html 

... but I need to redirect a page called "site.html?id=3"

RedirectMatch 301 site.html?id=3$ /newpage/1.html 

This code won't work, page won't load. I also am not able to put a ^ in front of the site.html. Anybody an idea how I can permanently move "site.html?id=3" to "newpage.html/3.html"? Is the "?" or "=" considered a regular expression?

g1smd

7:36 pm on Jun 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Mod_Alias rules only see the path and filename parts, and cannot 'see' the query string.

You need to use a Mod_Rewrite RewriteRule with an additional RewriteCond that looks at the QUERY_STRING.

This topic comes up every day, so there are a lot of prior examples and code.

jdMorgan

7:44 pm on Jun 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> I also am not able to put a ^ in front of the site.html.

Using the mod_alias RedirectMatch directive, you'd need to put "^/" in front of it.

However, mod_alias directives cannot see query strings attached to URLs, since they are not considered to be "part of a URL," only data attached to a URL, and intended to be passed to the resource at that URL.

You will need to use mod_rewrite, and use a RewriteCond to test the query string.

Also, if the static-looking URL is internally rewritten back to the script URL, you will need to test %{THE_REQUEST} to be sure that you only redirect requests for the dynamic URL when it is directly-requested by a client, and not as a result of that internal rewrite. That is, if you are not really replacing the script with a static HTML page, but rather just trying to change the URL, then you must do this to avoid an 'infinite' redirect-rewrite loop.

Furthermore, I recommend that if you use mod_rewrite for *any* internal rewrites or external redirects, you should use it for *all* redirects. This is because, since the Redirect and RedirectMatch directives are processed by one module, and the RewriteCond and RewriteRule directives are processed by a different module, their execution order is controlled by which module runs first, and not by the order that they appear in your config files. Even if they execute in the proper order now, there is no guarantee that they would continue to do so if your server configuration was modified by your host, or if your Apache version was upgraded.

Jim

[edited by: jdMorgan at 7:45 pm (utc) on June 6, 2009]

benni_203

8:10 pm on Jun 6, 2009 (gmt 0)

10+ Year Member



Thanks for the insights!

I was trying Rewrite before and ran into the same issue. It is only a single page I want to forward since I changed the database and site structure, and for that one site, all users (and google) still have the old link with dated content. A second RewriteRule is then putting it in the new structure connecting it to the updated content (which works for everything else on the page). Here is the actual code:


RewriteEngine on
RewriteRule ^site.html?id=firefox$ /en/win/Firefox_3.html #won't work
RewriteRule ^(.*)/(.*)/(.*).html$ sc.php?language_id=$1&platform_id=$2&application_name=$3 [L]

How would I do the RewriteCond for "id=firefox"? I understand how to get static static URLs into dynamic, but not the other way round.

I think the second half of your post is referring to the second rewrite. But as I use the same module now, I should be ok?

g1smd

8:24 pm on Jun 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



For your first rule, RewriteRule cannot 'see' query strings; you need an additional RewriteCond to test that. That first rule needs the domain name adding to the target and [R=301,L] flags too - it needs to be a redirect.

The multiple

(.*)
patterns are very inefficient; replace with
([^.]+)
or similar. This rule is a rewrite.

There's a lot of additional help in the forum charter linking to threads with useful information and example code that can help you.

jdMorgan

10:35 pm on Jun 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I noted that a RewriteCond was needed above, along with another important points. You will find that forums are ineffective for getting complete solutions if you do not read the posted answers very carefully.

Jim

benni_203

8:31 am on Jun 7, 2009 (gmt 0)

10+ Year Member



Thanks! I got it working. The only thing is that it add "?id=firefox" to the new URI. I also changed the (.*) accordingly.


RewriteCond %{QUERY_STRING} ^id=firefox$
RewriteRule ^site\.html$ /en/win/Firefox_3.html [R=301,L]

RewriteRule ^([^.]+)/([^.]+)/([^.]+).html$ sc.php?language_id=$1&platform_id=$2&application_name=$3 [L]


Also, if the static-looking URL is internally rewritten back to the script URL, you will need to test %{THE_REQUEST} to be sure that you only redirect requests for the dynamic URL when it is directly-requested by a client, and not as a result of that internal rewrite. That is, if you are not really replacing the script with a static HTML page, but rather just trying to change the URL, then you must do this to avoid an 'infinite' redirect-rewrite loop.

The old site still has to work for a while, because there are other id's with the old structure which are still current. Can my rewrites or anything else cause an infinite rewrite loop?

jdMorgan

12:56 pm on Jun 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Clear the query string on you redirect by adding a "?" to the substitution URL, as noted in the mod_rewrite documentation. Use a canonical URL in your external redirect rule.

Use correct negative-match subpatterns in your internal rewrite rule for better performance, and escape the literal periods in patterns:


RewriteCond %{QUERY_STRING} ^id=firefox$
RewriteRule ^site\.html$ [i]http://www.example.com[/i]/en/win/Firefox_3.htm[b]l?[/b] [R=301,L]
#
RewriteRule ^([b][^/]+)/([^/][/b]+)/([^.]+)[b]\.h[/b]tml$ sc.php?language_id=$1&platform_id=$2&application_name=$3 [L]

Can't say about your loop, as you didn't clearly state whether your were or were not actually replacing scripted pages with static HTML files.

Jim

benni_203

2:09 pm on Jun 7, 2009 (gmt 0)

10+ Year Member



thanks, guys! This was my first (now successful) mod_rewrite and I haven't been doing anything with .htaccess or perl before. Next time is going to be better.

g1smd

3:02 pm on Jun 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Can't say about your loop, as you didn't clearly state whether your were or were not actually replacing scripted pages with static HTML files.