.htaccess Add a parameter to query string if using certain subdomain - apache

I would like to add a fixed parameter to a URL if a certain sub domain is used, but otherwise leave the URL untouched.
For example:
http://subdomain.domain.com?foo=bar
would rewrite to
http://subdomain.domain.com?foo=bar&isMySub=true
but http://domain.com?foo=bar or http://othersubdomain.domain.com?foo=bar would remain untouched.
Ive looked around on here and so far all Ive been able to ascertain is that it will likely require the [QSA] flag so as to leave the rest of the query string intact.
This get me close, but some links and images break so it has to be messing up my url or query in ways I dont want.
RewriteCond %{HTTP_HOST} ^subdomain\.domain\.com(&|$)
RewriteRule .* index.php?foo=bar [QSA]

You can exclude requests for certain files using the %{REQUEST_URI} server variable and checking the extension:
RewriteCond %{REQUEST_URI} !\.(css|js|jpe?g|gif|png)$
RewriteCond %{HTTP_HOST} ^subdomain\.domain\.com
RewriteRule .* index.php?isMySub=true [QSA]
The [QSA] flag will pass the existing query string, such as ?foo=bar, so you don't have to.
Alternative rules for the above ruleset:
Send to index.php and add requested resource as the query variable req:
RewriteRule ^(.*)$ index.php?req=$1&isMySub=true [QSA]
The parenthesis () in the rule pattern capture the matching value into a variable. First set of parens goes to $1, second to $2, etc.
Or, send to same resource as is requested but with the added query variable.
RewriteRule ^(.*)$ $1?isMySub=true [QSA]

Related

RewriteRule to capture whole search string produces empty result

I have the following rule in .htaccess:
RewriteRule ^order(.*)$ /index.php?p=order&product=$1 [L,NC]
It's a simplification because later on I want to add order\?product=(.*)
I access the website with:
http://website.com/order?product=L0231-03868 but in the $_GET I'm only getting this:
Array ( [p] => skonfiguruj-zamowienie [product] => )
The product is empty. What am I missing?
-- edit
the moment I add the question mark
RewriteRule ^order\?(.*)$ /index.php?p=order&product=$1 [L,NC]
I get 404
Your URI doesn't really have anything after order so there is nothing to capture in (.*).
Use QSA flag to append original query string after rewrite.
No need to repeat order on both sides.
Suggested rule:
RewriteRule ^(order)/?$ index.php?p=$1 [L,NC,QSA]
Because of QSA flag, your original query string product=L0231-03868 will be appended to p=order and you will get both parameters in php file.
Note about patter ^order\?(.*)$ generating 404. Remember that a ? will never be part of URI to be matched using RewriteRule hence this pattern containing a ? is guaranteed to always fail.
With your shown samples please try following htacces rules file. Make sure to keep your htaccess rules file along with index.php file, order folder(3 of them should reside inside root directory). Also clear cache before testing your URLs.
RewriteEngine ON
RewriteCond %{THE_REQUEST} \s/(order)\?(product)=(\S+)\s [NC]
RewriteRule ^ index.php?p=%1&%2=%3 [QSA,L]
To make it more Generic, as above rules are very samples specific only:
RewriteEngine ON
RewriteCond %{THE_REQUEST} \s/([^?]*)\?([^=]*)=(\S+)\s [NC]
RewriteRule ^ index.php?p=%1&%2=%3 [QSA,L]
Documentation link:
%{THE_REQUEST} is being used here, which contains complete request line.

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.)

Rewriting subdirectory to query string parameter

I have two requirements;
That, for example, /product/12345 is internally redirected to /product/product.php?product=12345.
That if the user tries to access /product/product.php in the URL bar, it is redirected to /product/ for tidiness.
Separate, they both work correctly, but together it results in an infinite loop - I know that I'm redirecting from /product/ to /product.php and back again, but the difference is internal vs external and I'm not sure how to distinguish between them.
RewriteEngine On
RewriteRule ^product/product.php /product/ [NC,R=307,END]
RewriteCond %{REQUEST_URI} !^/product/product.php [NC]
RewriteRule ^product/(.*) /product/product.php?product=$1 [NC]
There probably exist other solutions, but it works if you change two things:
Add a condition to the first RewriteRule that checks if the query string is empty, i.e. product/product.php without query string redirects to /product/.
Change (.*) in the second RewriteRule to (.+) or ([0-9]+) to only rewrite requests containing a product id (requests to /product/ are not rewritten).
RewriteEngine On
RewriteCond %{QUERY_STRING} ="" [NC]
RewriteRule ^product/product\.php$ /product/ [NC,R=307,END]
RewriteCond %{REQUEST_URI} !^/product/product\.php [NC]
RewriteRule ^product/(.+) /product/product.php?product=$1 [NC]
access /product/product.php in the URL bar, it is redirected to /product/ for tidiness
You might as well also redirect /product/product.php?product=12345 to the corresponding canonical URL (ie. /product/12345) - which you can do all in the same rule. If the product ID is numeric only then you should restrict your regex accordingly - this will also avoid the need for an additional condition.
For example:
# Canonical redirect
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^(?:product=(\d*))?$ [NC]
RewriteRule ^product/product\.php$ /product/%1 [NC,R=307,L]
# Rewrite requests from "pretty" URL to underlying filesystem path
RewriteRule ^product/(\d*) /product/product.php?product=$1 [L]
The condition that checks against the REDIRECT_STATUS environment variable is necessary to prevent a redirect loop in this instance since the query string is entirely optional.
By restricting the match to digits-only, we avoid the need for an additional condition on the internal rewrite, product.php won't match. If the product id can contain letters then restrict the pattern to avoid dots (.), eg. ([^./]*).
Only include a NC flag on the internal rewrite if this is strictly necessary, otherwise this potentially creates a duplicate content issue.

apache query string rewrite rules

I am setting up Query string redirect :
expo.com/en/general/campaigns/on-second-thought.html?slide=ost-2016-tank to
expo.com/en/general/campaigns/on-second-thought/ost-2016-tank.html
RewriteCond %{HTTP_HOST} ^(.*)expo\.com
RewriteCond %{QUERY_STRING} slide=ost-2016-tank
RewriteRule  ^/en/general/campaigns/on-second-thought.html?$  http://www.expo.com/en/general/campaigns/on-second-thought/ost-2016-tank.html [R=301,L,NC]
redirect happening but its appending ?slide=ost-2016-tank like below
http://www.expo.com/en/general/campaigns/on-second-thought/ost-2016-tank.html?slide=ost-2016-tank
slide=ost-2016-tank parameter is added to redirected page
Since your rule does not define a new query string, the default behavior of Apache is to copy the old query string to the new URL. To get rid of it, append a ? to the address you rewrite/redirect to:
RewriteRule ^/en/general/campaigns/on-second-thought\.html?$ http://www.expo.com/en/general/campaigns/on-second-thought/ost-2016-tank.html? [R=301,L,NC]
Or, for Apache >= 2.4, you can also use the flag QSD (Query String Discard):
RewriteRule ^/en/general/campaigns/on-second-thought\.html?$ http://www.expo.com/en/general/campaigns/on-second-thought/ost-2016-tank.html [R=301,L,NC,QSD]
Simply add a blank query string when redirecting:
RewriteCond %{HTTP_HOST} ^(.*)expo\.com
RewriteCond %{QUERY_STRING} ^slide=(ost-2016-tank)$
RewriteRule ^(/?en/general/campaigns/on-second-thought)\.(html)$ $1/%1.$2? [R=301,L,NC]
No need to mention http://expo.com again when redirecting. It'll automatically redirect to the same hostname because of R flag. No need to repeat same strings over and over. Using match groups and referencing them later works.
Your pattern had .html?$ in it, which actually means that it'll match .html as well as .htm. You do not receive query strings in RewriteRule context.

How do I remove parts of a query string with RewriteCond and RewriteRule?

Background
I want to replace several (3) query string parameters in urls. We're moving to a new search engine and there are tons of links that we would like to still work. Examples:
http://example.com/search?q=s&restrictBy[foo]=fltr1&restrictBy[baz]=fltr2 ->
http://example.com/search?q=s&newfoo=fltr1&bazinga=fltr2
http://example.com/search?q=s&restrictBy[bar]=fltr3 ->
http://example.com/search?q=s&barista=fltr3
http://example.com/search?q=s&restrictBy[bar]=fltr1&restrictBy[baz]=fltr2&restrictBy[foo]=fltr3 ->
http://example.com/search?q=s&barista=fltr1&bazinga=fltr2&newfoo=fltr3
Problem
The first parameter to RewriteRule does not look at the query string, so I cannot replace a single parameter while keeping the rest of the url intact. Additionally, the fact that NONE, SOME, or ALL of the parameters may exist, and IN ANY ORDER is throwing me for a loop.
# Does not work :/
RewriteRule (.*)restrictBy\[foo\]=(.*) $1newfoo=$2
# Kinda works, but loses rest of params
RewriteCond %{QUERY_STRING} restrictBy\[foo\]=([^&]*)
RewriteRule (.*) $1?newfoo=%1 [L]
# Kinda works, but doesn't remove old params
RewriteCond %{QUERY_STRING} restrictBy\[foo\]=([^&]*)
RewriteRule (.*) $1?newfoo=%1 [QSA,L]
Question
How can I replace ANY OR ALL 3 params without losing data and without additional data?
Remove QSA from rule to overwrite existing query string:
RewriteCond ::%{QUERY_STRING} ::(?:|.*&)restrictBy\[foo\]=([^&]*)
RewriteCond %1::%{QUERY_STRING} (.*?)::(?:|.*&)restrictBy\[baz\]=([^&]*)
RewriteCond %1&%2::%{QUERY_STRING} ([^&]*)&(.*?)::(?:|.*&)q=([^&]*)
RewriteRule ^(.*)$ $1?q=%3&newfoo=%1&bazinga=%2 [L,R]