redirect htaccess URL with GET parameters - .htaccess

I'm trying to redirect using .htaccess, from example.com/products/category/subcat/name/?page=0 to example.com/example-subpage
my code not working:
RewriteCond %{REQUEST_URI} ^/products/category/subcat/name$
RewriteCond %{QUERY_STRING} ^page=0$
RewriteRule ^ https://example.com/example-subpage [R=301,L,QSD]

The issue probably is the handling of the trailing slash in your first condition. You'd need to include it into the condition:
RewriteCond %{REQUEST_URI} ^/products/category/subcat/name/$
RewriteCond %{QUERY_STRING} ^page=0$
RewriteRule ^ https://example.com/example-subpage [R=301,L,QSD]
I personally would always prefer a slightly more flexible matching with an optional trailing slash:
RewriteCond %{REQUEST_URI} ^/products/category/subcat/name/?$
RewriteCond %{QUERY_STRING} ^page=0$
RewriteRule ^ https://example.com/example-subpage [R=301,L,QSD]
That could be simplified to this:
RewriteCond %{QUERY_STRING} ^page=0$
RewriteRule ^/?products/category/subcat/name/?$ https://example.com/example-subpage [R=301,L,QSD]
And last not least it might make sense to add a bit of flexibility to the remaining condition to also match if other, unexpected arguments get added:
RewriteCond %{QUERY_STRING} (?:^|&)page=0(?:&|$)
RewriteRule ^/?products/category/subcat/name/?$ https://example.com/example-subpage [R=301,L,QSD]

Related

Are 3 identical parameters possible with .htaccess?

#anubhava and #RavinderSingh13 have helped me tremendously so far in understanding more about .htaccess and rewrite rules. However, even though both the first rule (with one parameter: $id) and the second rule (with two parameters: $id and $name) works for rewriting the url, my third rule I attempted with also two parameters ($id and $class) fails, and does not rewrite the final url. Below is my entire file so far. I would like to add that the $class parameter is in the format of a-class, b-class, etc., so maybe that could be a contributor to the the rewrite not working? Thank you for helping me continue to learn thus far!
RewriteEngine on
--1st rule with one parameter: $id--
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} id=([0-9]+) [NC]
RewriteRule ^file\.php$ /directory/%1? [R=301,L,NC]
RewriteRule ^directory/(\d+)/?$ /directory/file.php?id=$1 [L,QSA,NC]
--2nd rule with two parameters: $id and $name--
RewriteEngine on
RewriteCond %{THE_REQUEST} \s/file\.php\?id=(\d+)&name=(\S+)\s [NC]
RewriteRule ^ /directory/%1/%2? [R=301,L]
RewriteRule ^directory/(\d+)/(.*)/?$ /directory/file.php?id=$1&name=$2 [NC,L,QSA]
--My attempt at the third rule following the example from the second, but this rule fails. Parameters are $id and $class--
RewriteEngine on
RewriteCond %{THE_REQUEST} \s/file\.php\?id=(\d+)&class=(\S+)\s [NC]
RewriteRule ^ /directory/%1/%2? [R=301,L]
RewriteRule ^directory/(\d+)/(.*)/?$ /directory/file.php?id=$1&class=$2 [NC,L,QSA]
With your shown samples and considering class word will be there always in your 3rd url try following rules. Also you need not to write RewriteEngine ON many times, only 1 time starting of file is enough.
RewriteEngine on
##1st rule with one parameter: $id--
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} id=([0-9]+) [NC]
RewriteRule ^file\.php$ /directory/%1? [R=301,L,NC]
RewriteRule ^directory/(\d+)/?$ /directory/file.php?id=$1 [L,QSA,NC]
##Parameters are $id and $class
RewriteCond %{THE_REQUEST} \s/file\.php\?id=(\d+)&class=(\w+-class)\s [NC]
RewriteRule ^ /directory/%1/%2? [R=301,L]
RewriteRule ^directory/(\d+)/(\w+-class)/?$ /directory/file.php?id=$1&class=$2 [NC,L,QSA]
##Rule with two parameters: $id and $name--
RewriteCond %{THE_REQUEST} \s/file\.php\?id=(\d+)&name=(\S+)\s [NC]
RewriteRule ^ /directory/%1/%2? [R=301,L]
RewriteRule ^directory/(\d+)/(.*)/?$ /directory/file.php?id=$1&name=$2 [NC,L,QSA]

htaccess: Remove parameter from URL

# case: leading and trailing parameters
RewriteCond %{QUERY_STRING} ^(.+)?session=[0-9a-z]+&(.+)$ [NC]
RewriteRule (.*) /$1?%1&%2 [R=301,L]
# case: leading-only, trailing-only or no additional parameters
RewriteCond %{QUERY_STRING} ^(.+)?session=[0-9a-z]+$|^osCsid=[0-9a-z]+&?(.*)$ [NC]
RewriteRule (.*) /$1?%1 [R=301,L]
URL is:
https://www.test.com/test/?session=123
Shouldn't this cut off the ?session=123?
If not, how can I achieve this?
You can use this rule to remove a parameter from anywhere in the query string:
RewriteCond %{QUERY_STRING} ^(.*&)?session=[^&]*(?:&(.*))?$ [NC]
RewriteRule ^ %{REQUEST_URI}?%1%2 [L,R=301,NE]

How to use htaccess back-reference variables for RewriteCond?

I want to match PHPSESSID with query string part (?session_id=b0300e9317e626da2c3f9a45e28b5106) of a URL. But i am not able to do this. I think the second rule does not seem to work. What's my wrong?
RewriteCond %{HTTP_COOKIE} !PHPSESSID=(\w+) [NC]
RewriteCond %{HTTP_COOKIE}:%{QUERY_STRING} ^PHPSESSID=(.*?);:(?!.*?session_id=\1).* [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/? [R=302,L,NC]
Missing OR flag on first RewriteCond and both conditions are broken. It should be something like this:
RewriteCond %{HTTP_COOKIE} !(?:^|\s)PHPSESSID= [OR]
RewriteCond %{HTTP_COOKIE};;%{QUERY_STRING} !(?:^|\s)PHPSESSID=([^;]+).*?;;(?:.*?&)?session_id=\1(?:$|&)
RewriteRule ^ https://%{HTTP_HOST}/? [R=302,L]

Htaccess Rewrite single query string

I'm having an issue with a rather old siye. I have some generic URL's with a query string, that i want to 301 redirect, but I don't want to blanket re-direct the urls. I want to choose where each query string is being redirected as there are alot of different categories within the site. For example:
I want to change:
index.php?_a=viewCat&catId=199
to:
/garden-furniture/patio-furniture/garden-benches-garden-seats/cat_199.html
But ill want to change another catid to another URL of my choosing, completely different structure. The problem I'm having is with the code i've got, if I don't have a ? at the end of the destination url, it works, but appends the query string to the end, if I put it on the end, it doesn't redirect at all.
Code I'm using:
RewriteCond %{QUERY_STRING} ^_a=viewCat&catId=199
RewriteRule ^index\.php$ /garden-furniture/patio-furniture/garden-benches-garden-seats/cat_199.html? [L,R=301]
Any help would be appreciated!
EDIT: The rest of my htaccess
RewriteEngine On
RewriteRule ^conservatory/(.*)$ /conservatory-furniture/$1 [R=301,L]
RewriteRule ^dining-room/(.*)$ /dining-room-furniture/$1 [R=301,L]
RewriteRule ^garden/(.*)$ /garden-furniture/patio-furniture/$1 [R=301,L]
RewriteBase /
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule cat_([0-9]+)(\.[a-z]{3,4})?(.*)$ index.php?_a=viewCat&catId=$1&%1 [NC]
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule prod_([0-9]+)(\.[a-z]{3,4})?$ index.php?_a=viewProd&productId=$1&%1 [NC]
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule info_([0-9]+)(\.[a-z]{3,4})?$ index.php?_a=viewDoc&docId=$1&%1 [NC]
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule tell_([0-9]+)(\.[a-z]{3,4})?$ index.php?_a=tellafriend&productId=$1&%1 [NC]
RewriteCond %{QUERY_STRING} (.*)$
RewriteRule _saleItems(\.[a-z]+)?(\?.*)?$ index.php?_a=viewCat&catId=saleItems&%1 [NC,L]
If these are complete URLs, you could anchor the pattern at the start of the string
RewriteRule ^cat_([0-9]+)(\.[a-z]{3,4})?(.*)$ index.php?_a=viewCat&catId=$1&%1 [NC]
this would prevent an URL, which has cat_ inside being rewritten to index.php?....
And since you don't use the trailing optional part, you could eliminate this too
RewriteRule ^cat_([0-9]+) index.php?_a=viewCat&catId=$1&%1 [NC]
Another point is the RewriteCond with query string. If the query string is optional, you could remove the RewriteCond and modify the RewriteRules to
RewriteRule ^cat_([0-9]+) index.php?_a=viewCat&catId=$1 [QSA,NC]
So, all these would become
RewriteRule ^cat_([0-9]+) index.php?_a=viewCat&catId=$1 [QSA,NC]
RewriteRule ^prod_([0-9]+) index.php?_a=viewProd&productId=$1 [QSA,NC]
RewriteRule ^info_([0-9]+) index.php?_a=viewDoc&docId=$1 [QSA,NC]
RewriteRule ^tell_([0-9]+) index.php?_a=tellafriend&productId=$1 [QSA,NC]
RewriteRule ^_saleItems index.php?_a=viewCat&catId=saleItems [QSA,NC,L]

Can I use mod_rewrite to redirect to a URL with a zero-padded parameter?

I'm trying to use mod_rewrite to redirect URLs from a URL from an old host to a new one that uses a different URL format. The new host zero-pads the ID to six digits as follows:
Old URL:
http://www.example.com/script.cgi?page_id=123
Needs to redirect to:
http://archive.example.com/000123/
This is what I have so far:
RewriteCond %{QUERY_STRING} ^page_id=([0-9]+)$
RewriteRule ^script\.cgi http://archive.example.com/%1/? [R=301,L]
This is redirects to:
http://archive.example.com/123/
Is there any way to achieve the zero-padding with mod_rewrite or will I just have to write a handler script to redirect to the proper URL?
Here are two more elegant solutions:
Using N flag to add one zero at a time until we have six digits:
RewriteCond %{QUERY_STRING} ^(([^&]*&)*)page_id=([0-9]{1,5})(&.*)?$
RewriteRule ^script\.cgi$ $0?page_id=0%3 [N]
RewriteCond %{QUERY_STRING} ^([^&]*&)*page_id=([0-9]{6})(&.*)?$
RewriteRule ^script\.cgi$ http://archive.example.com/%2/? [R=301,L]
Using an additional RewriteCond to prepend five zeros and then get just the last six digits:
RewriteCond %{QUERY_STRING} ^(([^&]*&)*)page_id=([0-9]+)(&.*)?$
RewriteCond 00000%3 [0-9]{6}$
RewriteRule ^script\.cgi$ http://archive.example.com/%0/? [R=301,L]
The complex pattern applied on QUERY_STRING is just to consider additional URL parameters. And I prefer the second solution as it is just one rule and more comprehensive.
Not an elegant solution, but you can set up six different rules:
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{1})$
RewriteRule ^script\.cgi http://archive.example.com/00000%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{2})$
RewriteRule ^script\.cgi http://archive.example.com/0000%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{3})$
RewriteRule ^script\.cgi http://archive.example.com/000%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{4})$
RewriteRule ^script\.cgi http://archive.example.com/00%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{5})$
RewriteRule ^script\.cgi http://archive.example.com/0%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]+)$
RewriteRule ^script\.cgi http://archive.example.com/%1/? [R=301,L]
The other option is to use a RewriteMap and have a script generate the URL to redirect to.
RewriteMap zeropad prg:/usr/local/zeropad.pl
RewriteCond %{QUERY_STRING} ^page_id=([0-9]+)$
RewriteRule ^script\.cgi ${zeropad:%1} [R=301,L]
And /usr/local/zeropad.pl is an executable script containing something like
#!/usr/bin/perl
$| = 1; #We don't want buffering
while (<STDIN>) {
printf("http://archive.example.com/%06d/?\n",$_);
}
You can use whatever executable you like instead of a Perl one. The idea is to have it print out (with a trailing newline) the URL to redirect to. It has to work in a loop reading STDIN, as Apache will launch the script once and be calling the same instance repeatedly. It cannot buffer its output, because Apache will wait for its output (until a newline) before completing the rewrite.
Ok, I realized I could achieve the results I wanted with the following:
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{1})$
RewriteRule ^script\.cgi http://archive.example.com/00000%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{2})$
RewriteRule ^script\.cgi http://archive.example.com/0000%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{3})$
RewriteRule ^script\.cgi http://archive.example.com/0000%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{4})$
RewriteRule ^script\.cgi http://archive.example.com/00%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{5})$
RewriteRule ^script\.cgi http://archive.example.com/0%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^page_id=([0-9]{6})$
RewriteRule ^script\.cgi http://archive.example.com/%1/? [R=301,L]
Is there any other way to do this without the multiple rules though?

Resources