301 redirect old parameter names to new parameter names by htaccess - apache

I just changed two parameter names and wanna redirect old names to changed name ones with any values anywhere in URL. e.g:
product.php?colornew=anyvalue&productname=anyvalue
301 redirect to:
product.php?color=anyvalue&product=anyvalue
Please note that this is just an example and as I said these two parameter can be anywhere in URL with any value.

You can use this code to rename your query parameters in any URL:
RewriteEngine On
# rename query parameter colornew=>color
RewriteCond %{QUERY_STRING} ^(.*&)?colornew=([^&]*)(&.*)?$ [NC]
RewriteRule ^ %{REQUEST_URI}?%1color=%2%3 [NC]
# rename query parameter productname=>product
RewriteCond %{QUERY_STRING} ^(.*&)?productname=([^&]*)(&.*)?$ [NC]
RewriteRule ^ %{REQUEST_URI}?%1product=%2%3 [NC,NE,L,R=302]

Try :
RewriteEngine on
RewriteCond %{THE_REQUEST} \?colornew=([^&]+)&productname=([^&\s]+)
RewriteRule ^ %{REQUEST_URI}?color=%1&product=%2 [QSA,NC,NE,L,R=301]

A simple fix of anubhava's otherwise excellent answer:
RewriteEngine On
# rename query parameter colornew=>color
RewriteCond %{QUERY_STRING} ^(.*&)?colornew=([^&]*)(&.*|)$ [NC]
RewriteRule ^ %{REQUEST_URI}?%1color=%2%3 [NC]
# rename query parameter productname=>product
RewriteCond %{QUERY_STRING} ^(.*&)?productname=([^&]*)(&.*|)$ [NC]
RewriteRule ^ %{REQUEST_URI}?%1product=%2%3 [NC,NE,L,R=302]
The difference is, at the end of the rewrite condition, the question mark is removed and there is an added "or" operator: |.
The reason is that, without this change, the URL becomes product.php?color=anyvalue&product=anyvalue%3 when there is nothing filled by the final match - (&.*)? - because the question mark in that match section says it either exists or doesn't; and if it doesn't, %3 doesn't exist so it just becomes appended as a string. Instead, (&.*|) says the match can either be populated by an ampersand plus anything, or it can be populated by nothing. In this way, %3 becomes "" when there is nothing and %3 does not get appended to the string.

Related

.htaccess check header and domain conditions as chain

Sorry this might be an easy one.
I'd like to check if both matches. The value of my header and the HTTP_REFERER
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?alloweddomain.com [NC]
RewriteCond %{HTTP:X-SomeHeader} !somekey
RewriteRule ^ - [F]
Otherwise I'd like to block the User.
The header check works nicely, and the documents are only served when it is correct. However the HTTP_REFERER seems to be ignored. The resources are even served when it is nor present. F.e with curl. How do I need to change the conditions that both must match?
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?alloweddomain.com [NC]
RewriteCond %{HTTP:X-SomeHeader} !somekey
RewriteRule ^ - [F]
This is currently checking that both do not match. If the Referer header is not present, but somekey is passed then the request is not blocked.
You need an OR flag on the first condition. ie. If either do not match then block the request. For example:
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?alloweddomain.com [NC,OR]
RewriteCond %{HTTP:X-SomeHeader} !=somekey
RewriteRule ^ - [F]
You also need the = operator on the second CondPattern for an exact match, otherwise you are checking whether somekey exists anywhere in the passed header.
OR, reverse the logic:
RewriteCond %{HTTP_REFERER} ^http(s)?://(www\.)?alloweddomain.com [NC]
RewriteCond %{HTTP:X-SomeHeader} =somekey
RewriteRule ^ - [S=1]
RewriteRule ^ - [F]
If both match then the following rule that blocks the request is skipped.
UPDATE:
but a GET parameter, can you guide how I would do that? This is what I've tried RewriteCond %{QUERY_STRING} apikey!=somekey
With the RewriteCond directive you are performing a (regex) string comparison. The value of the QUERY_STRING server variable (ie. %{QUERY_STRING}) is compared against the string/regex apikey!=somekey. This will never match since you should be checking for the "string" apikey=somekey. The = (or !=) is not a comparison operator, it's just part of the string. (Not to be confused with the ! prefix operator on the CondPattern itself (as used above) that negates the whole expression.)
To check that the string "apikey=somekey" is not contained anywhere in the QUERY_STRING then use the CondPattern !apikey=somekey. However, this is potentially too broad, since (as mentioned) this is checking that the string is not contained anywhere in the QUERY_STRING. A query string of the form fooapikey=somekeybar would also be successful. You could instead perform an exact string comparison (as above). For example:
RewriteCond %{QUERY_STRING} !=apikey=somekey
That's OK if the query string can only consist of the apikey URL parameter and nothing else, but if you are potentially expecting other URL parameters on the same request, eg. foo=1&apikey=somekey&bar=1 or apikey=somekey then you need to resort to a regex of the form:
RewriteCond %{QUERY_STRING} !(^|&)apikey=somekey($|&)
The condition is successful when the URL parameter apikey=somekey (exact string) is not contained anywhere in the query string.

htaccess Redirect URL with GET Parameters

I have a URL that is in the format http://www.example.com/?s=query
I want to redirect this URL to http://www.example.com/search/query
I have the following .htaccess but I wanted to check if there is anything wrong with this. My RewriteRule looks a little wonky and I don't know if it will cause problems for other URLs.
RewriteEngine on
RewriteCond %{QUERY_STRING} ^s=(.*)$ [NC]
RewriteRule ^$ /search/%1? [NC,L,R]
I ran a test Here and it seems to redirect to the correct URL.
RewriteCond %{QUERY_STRING} ^s=(.*)$ [NC]
RewriteRule ^$ /search/%1? [NC,L,R]
You will likely need the NE (noescape) flag on the RewriteRule directive if you are receiving a %-encoded URL parameter value, otherwise the target URL will be doubly-encoded. The QUERY_STRING server variable is not decoded by Apache.
It also depends on how you are rewriting /search/query back to /?s=query (or presumably more like /index.php?s=query?) - presumably you are already doing this later in the config? You only want this redirect to apply to direct requests and not rewritten requests (otherwise you'll get a redirect loop). An easy way to ensure this is to check that the REDIRECT_STATUS env var is empty.
For example:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^s=(.*) [NC]
RewriteRule ^$ /search/%1 [NE,QSD,R,L]
Other points:
The QSD flag would be preferable (on Apache 2.4) to appending ? to the end of the susbtitution string in order to remove the query string.
The regex ^s=(.*) (the trailing $ was superfluous) does assume that s is the only URL parameter at the start of the query string. As it stands, everything is assumed to be part of this value. eg. s=foo&bar=1 will result in /search/foo&bar=1.
The NC flag on the RewriteRule directive is superfluous.
Should you also be checking for /index.php?s=<query>? (Or whatever file/DirectoryIndex is handling the request.)

htaccess environment variable based on query string without some pamameters

I want set a apache environment variable based on query string variable but without some parameters.
for example, i have this query string:
utm_source=foo&my_param=baz&utm_medium=bar&_t=9999
now, i want set a variable without utm_source and utm_medium:
my_param=baz&_t=9999
i know only the parameters to remove (utm_source & utm_medium)... the other are only an example...
i have wtrite this code:
RewriteEngine On
RewriteBase /
RewriteRule ^ - [E=CustomQueryString:%{QUERY_STRING}]
RewriteCond %{ENV:CustomQueryString} ^(.*)&?(utm_source|utm_medium)=[^&]+&?(.*)$ [NC]
RewriteRule ^ - [E=CustomQueryString:%1%3]
the output is
utm_source=foo&my_param=baz&_t=9999
why utm_source param persist?
i have also tried:
RewriteRule ^ - [E=CustomQueryString:%{QUERY_STRING}]
RewriteCond %{ENV:CustomQueryString} ^(.*)&?utm_source=[^&]+&?(.*)$ [NC]
RewriteRule ^ - [E=CustomQueryString:%1%2]
RewriteCond %{ENV:CustomQueryString} ^(.*)&?utm_medium=[^&]+&?(.*)$ [NC]
RewriteRule ^ - [E=CustomQueryString:%1%2]
the output is right!
a=b&my_param=baz&_t=9999
i don't undertand why this version not work!
RewriteCond %{ENV:CustomQueryString} ^(.*)&?(utm_source|utm_medium)=[^&]+&?(.*)$ [NC]
RewriteRule ^ - [E=CustomQueryString:%1%3]
This condition
RewriteCond %{ENV:CustomQueryString} ^(.*)&?(utm_source|utm_medium)=[^&]+&?(.*)$ [NC]
doesn't remove both utm_source and utm_medium, because it matches only one of them.
.* matches the longest possible string, including one of utm_source or utm_medium, whichever comes first. See also Repetition with Star and Plus, especially section Watch Out for The Greediness! and following, for a detailed explanation.
utm_source|utm_medium means in plain english: match either utm_source or utm_medium. So the regular expression matches
(.*) - %1, including utm_source
(utm_source|utm_medium)=[^&]+ - utm_medium=...
(.*) - %3, everything else after utm_medium
The second variant with two conditions and rules works, because first you remove utm_source=..., and then pass the remaining string to the second condition. There the utm_medium=... part is removed, and finally you have the desired string without both utm_source and utm_medium.
You may enclose the test string with &s. This guarantees, that you have always an ampersand before and after the utm_source=... part and allows to simplify the regular expression a little bit.
RewriteCond &%{ENV:CustomQueryString}& ^(.*)&utm_source=.+?&(.*)$ [NC]
Same goes for the second RewriteCond with utm_medium.
You can use these 2 rule to remove both query parameters:
RewriteRule ^ - [E=CustomQueryString:%{QUERY_STRING}]
# remove utm_source from query string and set env var
RewriteCond %{ENV:CustomQueryString} ^(.*&)?utm_source=[^&]*(?:&(.*))?$ [NC]
RewriteRule ^ - [E=CustomQueryString:%1%2]
# remove utm_medium from query string and reset env var
RewriteCond %{ENV:CustomQueryString} ^(.*&)?utm_medium=[^&]*(?:&(.*))?$ [NC]
RewriteRule ^ - [E=CustomQueryString:%1%2]
If we start with URL as /?utm_source=foo&my_param=baz&utm_medium=bar&_t=9999
After 2nd rule we will have:
$_SERVER["CustomQueryString"] becomes `my_param=baz&_t=9999`

Apache rewrite rule query string

I am trying to write a Rewriterule which takes a domain from a URL of the format
https://www.example.com/sample?TARGET=https%3A%2F%2Fwww.example.com%2Fexample%2Fhelp%3Fparam%3D1.
If the TARGET parameter is present I need to redirect the user to the value inside the TARGET query parameter. My rewrite rule is below:
RewriteCond %{QUERY_STRING} TARGET=([-a-zA-Z0-9_+]+)
RewriteRule ^(.*)$ %1? [R=302,L]
This does not work because of two problems:
%1? in the rewrite rule causes the rewrite to append the value of the TARGET query string to the existing domain.
The value of %1 only contains https rather than https%3A%2F%2Fwww.example.com%2Fexample%2Fhelp%3Fparam%3D1.
I understand that this might not be the best way to go ahead with this, and I am open to suggestions.
You can use this rule instead:
RewriteEngine On
RewriteCond %{QUERY_STRING} ^TARGET=(.+)$ [NC]
RewriteRule ^ %1? [NE,R=302,L]
Important to use .+ in regex to be able to capture all characters of the URL specified in TARGET parameter.
This will redirect:
http://yourdomain.com/?TARGET=https://www.example.com/example/help?param=1 to
https://www.example.com/example/help?param=1

rewrite condition for directory along with file

Any one please help me.I am new to .htaccess
I want to check the following condition
RewriteCond : IF !index.html AND !app/facebookapp/{[a-zA-Z0-9-/]}.html
RewriteRule : .....
My code is
RewriteCond %{REQUEST_URI} !index\.html
RewriteCond %{REQUEST_URI} app/facebookapp/^([a-zA-Z0-9-/]+).html$
RewriteRule ......
its not working
And one more question
if the request url is header.html
RewriteCond %{REQUEST_URI} header.html$
RewriteRule ^([a-zA-Z0-9-/]+).html$ position.php?position=$1 [L]
$l will return header.
if the request url is app/facebookapp/header.html
we write the same above condition $l will return app/facebookapp/header.my question is how to get only the filename ??
thanks
Part 1:
Looks to me like you've got the ^ character in the wrong place. In regex syntax, that denotes the beginning of the text but you've got some text before it. You could put it at the front of the thing, but I think in this case you could just get rid of it. Try this:
RewriteCond %{REQUEST_URI} !index\.html
RewriteCond %{REQUEST_URI} app/facebookapp/([a-zA-Z0-9-/]+).html$
RewriteRule ......
Part 2:
You'll need two matching groups, and to only use the second one in the right-hand side. The first one includes / as a valid character, and the second one does not. Let me know if this works better:
RewriteCond %{REQUEST_URI} header.html$
RewriteRule ^([a-zA-Z0-9-/]+)/?([a-zA-Z0-9-]+).html$ position.php?position=$2 [L]