Forum Moderators: phranque

Message Too Old, No Replies

.htaccess 301 Redirect using Query String

         

eminentstyle

1:38 pm on Oct 26, 2008 (gmt 0)

10+ Year Member



Hello, long time reader (lurker) and finally I have joined. Why? I need a htaccess expert I think because I am slowly going insane. :-)

I am trying to redirect some product pages from the old site to the new site to benefit page rank. The actual domain has not changed, just the structure.

For example, redirect from: www.example.co.uk/itemdetails.php?itemId=48
To: www.example.co.uk/category/item1.html

Here is the code I am trying to use but I think I am missing something as it is not working. Its not actually a new domain just structure:

RewriteCond %{QUERY_STRING} ^itemId=48 [NC]
RewriteRule /itemdetails\.php$ /category/item1.html [R=301,QSA,L]

Can anyone see where I am going wrong. The rule appears to be ignored and simply goes to the 404 page on the new site. Thanks in advance.

(Freely admit to being a designer rather than a coder but I understand the theory if not the practical.) Thanks in advance for any help you can provide.

Ben

g1smd

2:13 pm on Oct 26, 2008 (gmt 0)

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



RewriteRule cannot "see" the leading / from the requested URL (if this is going in .htaccess) so omit that / from the start.

The target of the redirect should also state the domain name not just the path to the new URL.

You may need to delete the QSA part, as you don't appear to want the query string data to be passed on.

You'll need a ? on the end of the target URL if you really want to clear the query string.

Be aware that Item 480 and 4800 and many others will also match and be redirected.

Is there an easy relationship between the old and new URL? If there is, one rule can cater for hundreds or thousands of URLs in one go.

Add some #notes to the line above your rule to describe what it does, so that it still makes sense in 6 months time.

You will also want to add a general non-www to www rule after the rule you have above.

eminentstyle

3:07 pm on Oct 26, 2008 (gmt 0)

10+ Year Member



@g1smd, thanks for the prompt reply.

I (think I)have now made the changes you suggested but it is still not working. It still resolves to the 404 page. FYI, I already have a redirect in place removing the www from the urls. (It is going in .htaccess btw)Here is what I now have.

## Product redirection from old urls to new structure
RewriteCond %{QUERY_STRING} ^itemId=1 [NC]
RewriteRule itemdetails\.php$ http://example.co.uk/category/product.html? [R=301,L]

Have you any suggestions?

g1smd

3:24 pm on Oct 26, 2008 (gmt 0)

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



is itemId the very first parameter in the request? Your condition requires it to be the first one.

Your www to non-www redirect must be placed after this one.

It should work. Flush the browser cache and try again.

eminentstyle

4:42 pm on Oct 26, 2008 (gmt 0)

10+ Year Member



Thanks g1smd, you were right. Its a magento install and I have just noticed another reference further up that seems to be conflicting with the RewriteRule.

RewriteRule .* index.php [L]

If I comment this out, the site ceases to work. If I put the new rewrite above this line the rule works but there are then issues with images not appearing.

Any suggestions or should I try the magento guys. Here is the complete .htaccess file:


############################################
## uncomment these lines for CGI mode
## make sure to specify the correct cgi php binary file name
## it might be /cgi-bin/php-cgi

# Action php5-cgi /cgi-bin/php5-cgi
# AddHandler php5-cgi .php

############################################
## GoDaddy specific options

# Options -MultiViews

## you might also need to add this line to php.ini
## cgi.fix_pathinfo = 1
## if it still doesn't work, rename php.ini to php5.ini

############################################
## this line is specific for 1and1 hosting

#AddType x-mapp-php5 .php
#AddHandler x-mapp-php5 .php

############################################
## default index file

DirectoryIndex index.php

<IfModule mod_php5.c>

############################################
## adjust memory limit

# php_value memory_limit 64M
php_value memory_limit 128M
php_value max_execution_time 18000

############################################
## disable magic quotes for php request vars

php_flag magic_quotes_gpc off

############################################
## disable automatic session start
## before autoload was initialized

php_flag session.auto_start off

############################################
## enable resulting html compression

#php_flag zlib.output_compression on

###########################################
# disable user agent verification to not break multiple image upload

php_flag suhosin.session.cryptua off

###########################################
# turn off compatibility with PHP4 when dealing with objects

php_flag zend.ze1_compatibility_mode Off

</IfModule>

<IfModule mod_security.c>
###########################################
# disable POST processing to not break multiple image upload

SecFilterEngine Off
SecFilterScanPOST Off
</IfModule>

<IfModule mod_deflate.c>

############################################
## enable apache served files compression
## [developer.yahoo.com...]

# Insert filter
#SetOutputFilter DEFLATE

# Netscape 4.x has some problems...
#BrowserMatch ^Mozilla/4 gzip-only-text/html

# Netscape 4.06-4.08 have some more problems
#BrowserMatch ^Mozilla/4\.0[678] no-gzip

# MSIE masquerades as Netscape, but it is fine
#BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
# Don't compress images
#SetEnvIfNoCase Request_URI \.(?:gif¦jpe?g¦png)$ no-gzip dont-vary

# Make sure proxies don't deliver the wrong content
#Header append Vary User-Agent env=!dont-vary

</IfModule>

<IfModule mod_ssl.c>

############################################
## make HTTPS env vars available for CGI mode

SSLOptions StdEnvVars

</IfModule>

<IfModule mod_rewrite.c>

############################################
## enable rewrites

Options +FollowSymLinks
RewriteEngine on

############################################
## you can put here your magento root folder
## path relative to web root

#RewriteBase /magento/

############################################
## workaround for HTTP authorization
## in CGI environment

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

############################################
## always send 404 on missing files in these folders

RewriteCond %{REQUEST_URI} !^/(media¦skin¦js)/

############################################
## never rewrite for existing files, directories and links

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l

############################################
## rewrite everything else to index.php

RewriteRule .* index.php [L]

</IfModule>

############################################
## Prevent character encoding issues from server overrides
## If you still have problems, use the second line instead

AddDefaultCharset Off
#AddDefaultCharset UTF-8

<IfModule mod_expires.c>

############################################
## Add default Expires header
## [developer.yahoo.com...]

ExpiresDefault "access plus 1 year"

</IfModule>

############################################
## By default allow all access

Order allow,deny
Allow from all

############################################
## If running in cluster environment, uncomment this
## [developer.yahoo.com...]

#FileETag none

############################################
## Product redirection from old urls to new structure

RewriteCond %{QUERY_STRING} ^itemId=1 [NC]
RewriteRule itemdetails\.php$ http://example.co.uk/category/product.html? [R=301,L]

RewriteCond %{HTTP_HOST} ^www.example.co.uk$ [NC]
RewriteRule ^(.*)$ http://example.co.uk/$1 [R=301,L]
redirect 301 /underfloor.htm /under-floor-safes
redirect 301 /wallsafe.htm /wall-safes
redirect 301 /utility.htm /utility-safes
redirect 301 /postagereturns.htm /customer-service#answer3
redirect 301 /order.php /checkout/
[/code]

g1smd

5:42 pm on Oct 26, 2008 (gmt 0)

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



I'll let jd pick this apart in detail, but I will say that the designers have committed several obvious sins.

They have rules using both RewriteRule and Redirect within the same .htaccess file - and that means you can never be sure which order they will be processed. This is because Redirect comes from Mod_Alias and RewriteRule comes from Mod_Rewrite and the processing order depends on the order the modules are loaded in the httpd.conf file.

The last 7 lines also cause a redirection chain when a www URL is requested. The first rule changes from www to non-www and then another rule changes the URL path. That's multiple requests that are bounced between the browser and the server - a redirection chain (and that is bad).

What should happen is that the www to non-www rule should be absolutely last, and the other 5 rules should be changed to (1) use RewriteRule (with [R=301,L]) instead of Redirect and (2) each RewriteRule should include the domain name in the target so that each rule fixes that at the same time as fixing the path. Therefore, the general "www to non-www rule" should only run if none of the other preceding rules above have done so.

eminentstyle

11:09 am on Oct 27, 2008 (gmt 0)

10+ Year Member



Ok, this crash course is certainly giving me a much better understanding of the theory. Thanks g1smd.

FYI, the last 9 lines are the bits I have added. (I have not manually edited anything else in the file, though changes could have been made through the admin I assume)

SO based on your statements I have made the following changes:

############################################
## Product redirection from old urls to new structure

RewriteCond %{QUERY_STRING} ^itemId=3 [NC]
RewriteRule itemdetails\.php$ http://example.co.uk/category/product.html? [R=301,L]

RewriteRule /underfloor.htm http://example.co.uk/under-floor-safes [R=301,L]
RewriteRule /wallsafe.htm http://example.co.uk/wall-safes [R=301,L]
RewriteRule /utility.htm http://example.co.uk/utility-safes [R=301,L]
RewriteRule /postagereturns.htm http://example.co.uk/customer-service#answer3 [R=301,L]
RewriteRule /order.php http://example.co.uk/checkout/ [R=301,L]

RewriteCond %{HTTP_HOST} ^www.example.co.uk$ [NC]
RewriteRule ^(.*)$ http://example.co.uk/$1 [R=301,L]

This unfortunately is not working and now my redirects e.g underfloor.htm no longer work when they did before. Argh! :-)

g1smd

11:41 am on Oct 27, 2008 (gmt 0)

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



If this code is in .htaccess then note that RewriteRule cannot "see" any of the preceding path information for any URL that is presented to it. The input is localised to the folder where it applies to. In the case of root, that's just the leading "/" omitted.

^(.*)$
will also simplify to
(.*)
too.

If the URL request example.co.uk/wall-safes is later rewitten back to the internal server filepath /wallsafe.htm then your redirects here will each need a RewriteCond to test that /wall-safes was in the original THE_REQUEST and not in the local variable simply as a result of the rewrite changing it.

eminentstyle

9:30 pm on Oct 30, 2008 (gmt 0)

10+ Year Member



@g1smd, thanks for all your help but I feel as though I am getting nowhere. Should I remove the leading "/" and can you give me an example about the RewriteCond?

I am thoroughly stumped still!

jdMorgan

9:50 pm on Oct 30, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



In the spirit of helping yourself, have you tried removing the leading slashes?

If underfloor.htm is in the Web root directory, that is, if its URL is example.co.uk/underfloor.htm, then the correct syntax for your first per-page rule is:


RewriteRule ^underfloor\.htm$ http://example.co.uk/under-floor-safes [R=301,L]

Try that and if it works, make the same changes to the rest of your rules.

The "^" and "$" start and end anchors are explained in the regular-expressions tutorial linked from our Forum Charter.

Jim

g1smd

9:56 pm on Oct 30, 2008 (gmt 0)

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



Modified from a recent example posted last week:

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /wall-safes\ HTTP/ [NC]

eminentstyle

12:02 am on Oct 31, 2008 (gmt 0)

10+ Year Member



Thanks very much.

In the true spirit of helping myself I have indeed already tried removing the prevailing slashes with no luck. :-)

However I have not since attempted your subsequent suggestions. I will asap but my bed is calling me.

Much obliged and will keep you posted on the results. I bet you are on tender hooks! :-) Thanks again, Ben

Fotiman

2:25 pm on Oct 31, 2008 (gmt 0)

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



When you have your final solution, could you post it here? I know someone who is going to be doing the same thing soon and it would be helpful to see what worked for you. Thanks.

[edited by: Fotiman at 2:25 pm (utc) on Oct. 31, 2008]