Forum Moderators: phranque

Message Too Old, No Replies

htaccess redirect with parameters

Can't find how to redirect a list of single pages

         

Shrike99

7:18 pm on Dec 21, 2008 (gmt 0)

10+ Year Member



Hi,

Quick question for you, I guess you will find this easy, but I can't make it work.

Here is the situation, using a Wordpress blog:

I would like to do about 10 redirections in my .htaccess file.

As examples:
1- redirecting http://www.example.com/index.php3?nom=abc to http://www.example.com/def

2- redirecting http://www.example.com/www/index.php3?php=yyy to
http://www.example.com/zzz

3- http://www.example.com/ddd to http://www.example.com/eee

Since I don't have lots of them to redirect, I don't think I need a complicated redirect, I don't mind hardcoding 10 lines in my .htacess file.

Thanks a lot for your help.

jdMorgan

7:42 pm on Dec 21, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Please post your best effort code as a baseline for discussion.

Thanks,
Jim

Shrike99

8:01 pm on Dec 21, 2008 (gmt 0)

10+ Year Member



OK, here is what I tried:

Redirect 301 /index.php3?nom=abc http://www.example.com/def

The 301 does not work, as I still get a 404 without being redirected.

It does work now though for my example #3 (redirecting http://www.example.com/ddd to http://www.example.com/eee) with the following code:
Redirect 301 /ddd http://example.com/eee

So my problem seems to be with the parameters...

jdMorgan

8:18 pm on Dec 21, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes, mod_alias directives such as Redirect and RedirectMatch cannot "see" query strings appended to URLs -- Note that terminology there, as it is key; A URL locates a resource -- as its name states. But a query string is data to be passed to that resource (e.g. a script), and plays no part in locating it on the Web. Therefore, directives which examine only URLs pay no attention to query strings.

The solution is to use mod_rewrite instead of mod_alias, and to check the query string explicitly. Here is an example for your first case:


Options +FollowSymLinks
RewriteEngine on
#
RewriteCond %{QUERY_STRING} ^nom=abc$
RewriteRule ^index\.php3$ http://www.example.com/def? [R=301,L]

The first line may or may not be needed, and may or may not be allowed on your server. The only way to find out is to test.

In either case, those first one or two lines need only appear once at the top of your "list" of mod_rewrite rule.

Note also that you should not mix mod_alias and mod_rewrite directives on any site which may move to another server in the future. This is because you will have no control over whether that server processes mod_alias directives before processing mod_rewrite directives, or vice-versa. Varying the order of execution can have unexpected (and unpleasant) results on the operation of your server, and that is not something you'll want to be dealing with at the same time as a server move.

The question mark at the end of the substitution (new) URL is not a literal; It is a mod_rewrite token which in this case acts to remove the existing query string from the new URL. It will *not* appear in the redirected-to URL.

See the Apache mod_rewrite documentation and the Apache URL Rewriting Guide for more information. Links to these and to other useful resources are cited in our Forum Charter (see link at top left of this page).

Jim

Shrike99

1:55 am on Dec 22, 2008 (gmt 0)

10+ Year Member



Oh, I see this is much more complex than I thought.

I used your code and it works fine though. I applied it to my pages without problems. Thanks a lot. I will read the Apache mod_rewrite documentation, it is very interesting.

Thank a lot again, and have a great evening!

pendaco

7:30 pm on Jan 26, 2009 (gmt 0)

10+ Year Member



Hey guys, I found this thread through a nice little google search.

I'm currently working on a few rewrites and want to remove the parameters from a couple of urls.

Original:
www.example.com/random-category/random-title/?lang=en

New (what i'm trying to achieve):
www.example.com/random-category/random-title/

Please note that the categories and titles may vary and are not fixed (hence the 'random' ;-) ).

I've only come this far:
RewriteCond %{QUERY_STRING} ^lang=en$
RewriteRule ^(.*)$ http://www.example.com? [R=301,L]

So it matches the query string but i already know that my rewriterule is completely off since it redirects the links containing the string to my main page xD

The problem is that i have no clue how to setup the rewriterule for all those random urls.. Could someone nudge me in the right direction?

[edited by: jdMorgan at 11:06 pm (utc) on Jan. 26, 2009]
[edit reason] example.com [/edit]

g1smd

9:23 pm on Jan 26, 2009 (gmt 0)

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



Replace the question mark with
/$1?
so that the same URL but without the parameters is the target of the redirect.

Note that

^(.*)$
simplifies to
(.*)
too.

Note that your code won't redirect if lang=en is present but there are additional parameters present.

pendaco

9:51 pm on Jan 26, 2009 (gmt 0)

10+ Year Member



Thnx for your reply g1smd

Replace the question mark with /$1? so that the same URL but without the parameters is the target of the redirect.

Aah ke, i see they are now just following their original links but I got that working without any rewrite rules as well :-P

Note that ^(.*)$ simplifies to (.*) too.

Hmm, i always thought you had to open and close them with at ^ and $ ?

Note that your code won't redirect if lang=en is present but there are additional parameters present.

So what you're saying is that the RewriteCond isn't necessary or is the (.*) not correct?

jdMorgan

10:50 pm on Jan 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Take a quick tour through the resources cited in our forum charter, especially the regular-expressions tutorial: It's clear from the "open and close" phrase above that some attention to the concept of "anchoring" in regular expressions is needed.

Not to be an old moldy sock, but the chances of success with mod_rewrite is essentially zero until both regular expressions and mod_rewrite's RewriteRule and RewriteCond directives are thoroughly understood.

"^" means "Starts with" and "$" means "End with." Used in combination, an exact match will be required.

As for the "random-title," it's not clear at what "level" that randomness applies; That is, it isn't clear whether you mean to say that each destination URL is not directly-derivable from the source URL (by adding characters, dropping characters, or re-arranging characters) or not. If the old URL does not contain all of the information needed to construct the new URL, then you'll need one rule per URL (to keep the code simple).

Also, be aware that in order to "change your URLs" you must change them in the links on your HTML pages. Mod_rewrite can be used to map those new URLs (when requested by a client) to the existing server filepaths, and it can be used to tell the search engines to pass the PageRank/link-popularity of the old URL to the new ones more quickly, but it cannot "change the URLs" because URLs are used on the Web and are defined on the Web; Only filepaths are defined (and definable) within the server.

This may be a bit clearer if you realize that the basic *purpose* of a server is to translate URLs defined on the Web to filepaths defined in the server filesystem, and to make the URLs (Uniform Resource Locators) independent of the server's operating system and filesystem conventions.

Jim

SyntaxTerror

10:01 am on May 19, 2009 (gmt 0)

10+ Year Member



This thread has been most helpfull in getting me on my way to a very similar problem of rewriting (stripping) url's, in my case of the '?=virtuemart' parameter. I am so close now to the final result, but can't wrap my head around what I am doing wrong. I hope someone can help me out. I use the following rule:

RewriteCond %{QUERY_STRING} ^(.+)&virtuemart=[0-9a-z]+$¦^virtuemart=[0-9a-z]+&?(.*)$ [NC]
RewriteRule ^(.*) $1?%1 [R=301,L]

Now this does strip the parameter from the URL, but the resulting URL gives a 404, it seems to append folder structure of my hosting to my url. So instead of redirecting to http://www.example.com/page.html it goes to http://www.example.com/www/htdocs/user/page.html

I know I must be close now... but just can't work this one out!

btw: first post here, Id like to include a thanks for all the help I've gotten from everyone just reading the many topics :)

[edited by: SyntaxTerror at 10:03 am (utc) on May 19, 2009]

SyntaxTerror

11:02 am on May 19, 2009 (gmt 0)

10+ Year Member



...aand, I figured it out, I was missing a single / in the RewriteRule

Changed it to:

RewriteCond %{QUERY_STRING} ^(.+)&virtuemart=[0-9a-z]+$¦^virtuemart=[0-9a-z]+&?(.*)$ [NC]
RewriteRule ^(.*) /$1?%1 [R=301,L]

..works like a charm :)

jdMorgan

1:25 pm on May 19, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It's likely that the code does not work properly if the second case in the RewriteCOnd is matched. This is because in that case, the value matched by the first set of parentheses will be blank, and therefore %1 will be blank. The value you wanted will be in %2 instead.

The solution is to use two separate RewriteConds. In this case, the values of %1-%9 will be set by the last RewriteCond that matches.


# accept optional parm(s) before virtuemart name/value, but none after
RewriteCond %{QUERY_STRING} ^(([^&]*(&[^&]*)*)&)?virtuemart=[0-9a-z]+$ [OR]
# require parm(s) before and accepts optional parm(s) after virtuemart name/value
RewriteCond %{QUERY_STRING} ^(([^&]*(&[^&]*)*)&)virtuemart=[0-9a-z]+((&[^&]*)*)$
RewriteRule ^(.*)$ http://www.example.com/$1?%2%4 [R=301,L]

Here, %2 holds the "start" of the query string, but omits its trailing "&". If additional name/value pairs follow the virtuemart parameter, then those, along with their leading "&" will be in %4. So, this code handles the case where "virtuemart=" is the only name/value pair, where additional name/value pairs precede "virtumart=", where additional name/value pairs follow virtuemart, or where additional name/value pairs both precede and follow "virtuemart=".

It's a bit tricky because the back-references must be "lined up" between the two RewriteConds in order to make sure that %2 and %4 contain the correct parameters in any case, so be careful with the parentheses nesting if you make any adjustments!

Note also that a protocol and a canonical hostname should be specified whenever the [R=30x] flag is used, in order to avoid problems with UseCanonicalName.

Jim

[edit] Corrections as noted below. [/edit]

[edited by: jdMorgan at 4:28 pm (utc) on May 19, 2009]

SyntaxTerror

2:03 pm on May 19, 2009 (gmt 0)

10+ Year Member



I admit the whole .htacces way of writing things is still very cryptic to me. So I appreciate you taking the time to explain. Now I have tried your code, in place of my hack-copy-paste-trial-and-error bit. It seems to leave the virtuemart parameter in tact, not removing it.

The bit of code I used originally came from an osCommerce reference elsewhere on the web, I hadn't understood it took into account parameters after or before.

In my case, I always know that ?virtuemart= is the only parameter present in the url, beside page name obviously.

Does this simplify things? Can I take out the second part of my original re-write as so?:

#RewriteCond %{QUERY_STRING} ^(.+)&virtuemart=[0-9a-z]+$ [NC]
#RewriteRule ^(.*) /$1?%1 [R=301,L]

[edited by: SyntaxTerror at 2:07 pm (utc) on May 19, 2009]

jdMorgan

4:34 pm on May 19, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



While merging your pattern with the ones in my RewriteConds above, I inadvertently omitted the quantifiers on your "virtumart" value patterns -- See corrections to my post above.

However, if you *know* that only the "virtuemart" name/value pair will ever be present, then you could use:


RewriteCond %{QUERY_STRING} ^virtuemart=[0-9a-z]+$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1? [R=301,L]

However, it might then be easy to "break" your site by simply making a linking error (accidentally or maliciously).

Jim

[edited by: jdMorgan at 4:44 pm (utc) on May 19, 2009]

SyntaxTerror

6:50 pm on May 19, 2009 (gmt 0)

10+ Year Member



Seeing how things might change in the future, I have used your previous solution, I realise this is more robust and flexible.

It works perfectly too. :) I've been trying to tackle this for some time now.. Thanks Jim!