Remove Query String from the end of the URL after passing through Rewrite Map - apache

I have a list of several hundred URL redirects/rewrites inside of a rewrite map. Most of the URL's contain query strings that match a specific entry in the rewrite map. I found this question on how to pass the query string into the rewrite map. I got this working fine but the problem now is that the existing query string is appended to the end of the rewritten URL. For example:
Expected Rewrite:
/subdir/dir.cfm?categoryID=123 -> https://example.com/subdir/endurl
Actual Rewrite:
https://example.com/subdir/endurl?categoryID=123
Expected Rewrite
/subdir/dir.cfm?videoID=3422424-131FDDFD-234 -> https://example.com/subdir/awesome/stuff
Actual Rewrite:
https://example.com/subdir/awesome/stuff?videoID=3422424-131FDDFD-234
This is the rewrite rules I have:
RewriteEngine on
RewriteMap redirects dbm=sdbm:C:\Apache24\conf\redirects.sdbm
RewriteCond ${redirects:$1} !=""
RewriteRule ^(.*\.(cfm|cfml)) ${redirects:$1?%{QUERY_STRING}} [NC,R=301,L]
How can I remove the query string appended to the URL after the rewrite?
EDIT
I was able to actually get this working using this:
RewriteMap redirects dbm=sdbm:C:\Apache24\conf\redirects.sdbm
RewriteCond ${redirects:$1} !=""
RewriteRule ^(.*\.(cfm|cfml)) ${redirects:$1?%{QUERY_STRING}} [NC,C]
RewriteRule (.*) $1? [L,R=301]
However I am not sure if someone knows of a better way to accomplish what I am doing? I am thinking this might break if I ever have to redirect to a URL that contains a query string to another url that contains a query string.

In Apache version 2.4.0 and later, you can use [QSD] flag (Query String Discard):
RewriteRule ^(.*\.(cfm|cfml)) ${redirects:$1?%{QUERY_STRING}} [QSD,NC]
In Apache version 2.2, there is no [QSD] flag, but if the replacement URI contains a query string, the default behavior of RewriteRule is to discard the existing query string, so by just adding a ? to your rewrite URI, you will get the same effect:
RewriteRule ^(.*\.(cfm|cfml)) ${redirects:$1?%{QUERY_STRING}}? [NC]
(your newly added rewrite rule actually uses this feature)

Related

Can't pass parameters to another redirect website

I want to redirect to another website, and pass the parameters also.
Example: I go to my website: source.example/?code=12345
Then, I want it to redirect to target.example/?code=12345.
I am currently using this for my .htaccess file, since I figured out from other posts that if I query a certain parameter, it will get passed also:
RewriteEngine On
RewriteCond %{QUERY_STRING} ^code=[NS]$
RewriteRule "www.google.com" /$1 [R=302,L]
Also, I tried many different approaches looking at these stack questions:
simple .htaccess redirect : how to redirect with parameters?
Redirect and keep the parameter in the url on .htaccess
But I can't get it running :(
since I figured out from other posts that if I query a certain parameter, it will get passed also
This is not true. The query string is passed through by default - there is nothing extra you need to do if you want the same query string on the target URL.
RewriteCond %{QUERY_STRING} ^code=[NS]$
RewriteRule "www.google.com" /$1 [R=302,L]
This code won't match the source URL for many reasons:
"www.google.com" - The first argument to the RewriteRule directive is a regex that matches the source URL-path (less the slash prefix). In your example the URL-path is empty.
^code=[NS]$ matches either code=N or code=S - which is not the intention from your example. (The [NS] looks like a mangled RewriteRule flag?!)
/$1 - this is the substitition string, ie. the URL you want to redirect to. (The $1 backreference is always empty, so this is meaningless.)
To redirect from source.example/?code=<number> to https://target.example/?code=<number> then try the following instead:
RewriteCond %{HTTP_HOST} ^source\.example [NC]
RewriteCond %{QUERY_STRING} ^code=\d+$
RewriteRule ^$ https://target.example/ [R=302,L]
This only matches a query string of the form code=1234. It does not match code= or code=1234&foo=bar, etc.
The query string is passed through by default.
If source.example is the only domain being hosted at the current location then you can remove the first condition that explicitly checks the requested hostname.
The order of directives in the .htaccess file is important. An external redirect like this should go near the top.

Rewrite rule to redirect a URI without a query param after appending a query param

I need to check if a UIRI from a folder contains any query param and if not, add the query param and redirect the uri in browser also using Apache rewrite rule. For this all url's starting with /abc/def/xyz/ the url should be appended with ?v=2, if not already having a query param
For example, /abc/def/xyz/folder/test.pdf should become /abc/def/xyz/folder/test.pdf?v=2
But /abc/def/xyz/folder1/test.pdf?v=3 should be left untouched.
I was able to add the query param using below but it causes infinite redirects. Thats why I need the selective redirect
RewriteRule ^abc/def/xyz/(.*) /abc/def/xyz/$1?v=2 [L,R=301]
the below does not redirect the browser URL to the new URI with the query param:
RewriteRule ^abc/def/xyz/(.*) /abc/def/xyz/$1?v=2 [PT,L]
You can make use of RewriteCond to check for Query Strings. I guess the following should do the trick. If there is a query String available, it would skip the rule. Else, it would append the query string v=2
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^abc/def/xyz/(.*)$ /abc/def/xyz/$1?v=2 [L, R=301]
Hope it helps.

Redirect www to non-www loses Google gclid tracking code

I've used the .htaccess code in Generic htaccess redirect www to non-www to successfully redirect www.mysite.com to mysite.com, however in the process it strips off the gclid parameter and now AdWords isn't counting clicks correctly.
Is it possible to amend the code below so that any parameters are retained after the redirect?
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
From: https://wiki.apache.org/httpd/RewriteFlags/QSA
QSA = Query String Append.
This rule appends the GET query string which results from the ReWrite rule to the initial GET query string sent by the browser. For example, take the following RewriteRule:
RewriteRule ^/product/([0-9]*)/? /product.php?product_id=$1 [QSA]
This simply makes the product_id number look like a directory to the user. Now say that I have two different views of the page, view=short and view=long. For whatever reason, I don't want to make these views look like directories by using a RewriteRule. So I want to be able to do things like:
http://example.com/product/1351283/?view=short
Let's see how QSA works. With QSA, my final rewritten URL is
http://example.com/product.php?product_id=1351283&view=short
QSA has caused the RewriteEngine to append the existing query string (view=short) to the new query string (product_id=1351283). Without QSA, the existing query string is simply replaced by the new query string:
http://example.com/product.php?product_id=1351283
If you do much scripting with reliance on GET variables, it is virtually imperative that you enable the QSA flag on all of your RewriteRules.

.htaccess - silently rewrite/redirect everything to internal subfolder

Let's say I have thiswww.example.com site structure:
/srv/http/
/srv/http/site/index.php
/srv/http/site/stuff.php
I want the following rewrites/redirects to happen:
www.example.com/index.php -> redirects to -> www.example.com/site/index.php -> but the user sees -> www.example.com/index.php
www.example.com/stuff.php -> redirects to -> www.example.com/site/stuff.php -> but the user sees -> www.example.com/stuff.php
In general, everything after www.example.com/ redirects to www.example.com/site/. But the user sees the original URL in the browser.
I've looked around on the internet but haven't managed to figure out what to use in this particular situation.
I tried rewriting everything:
RewriteEngine On
RewriteRule ^$ /site [L]
but index.php disappears and www.example.com/site/ is shown to the user.
How can I use .htaccess to solve this problem?
You need to capture the url request incoming into the server, like this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/site/
RewriteRule ^(.*)$ /site/$1 [L,QSA]
The QSA is (eventually) to also append the query string to the rewritten url
Same idea as #guido suggested, but a bit shortened using negative lookahead
RewriteEngine On
RewriteRule ^(?!site/)(.*)$ site/$1 [L]
Note: I am not using QSA flag as we are not adding additional parameters to the query string for the replacement URL. By default, Apache will pass the original query string along with the replacement URL.
http://www.example.com/index.php?one=1&two=2
will be internally rewritten as
http://www.example.com/site/index.php?one=1&two=2
If you really want add a special parameter (ex: mode=rewrite) in the query string for every rewrite, then you can use the QSA Query String Append flag
RewriteEngine On
RewriteRule ^(?!site/)(.*)$ site/$1?mode=rewrite [L,QSA]
Then this will combine mode=rewrite with original query string
http://www.example.com/index.php?one=1&two=2
to
http://www.example.com/site/index.php?mode=rewrite&one=1&two=2
RewriteEngine On
RewriteRule ^(.*)$ site/index.php?var=$1 [L]
With this rule, i'm passing all requests to site/index.php, so you could get the requested uri via $_GET['var'], and then you'll make the index.php serve the requested url behind the scene without the url changing in the user's browser. Ciao.

Remove query string from url using rewrite rule

Im trying to rewrite url in htaccess file.
Original url:
www.mywebsite.com/flash/module.swf?xmlpath=http%3a%2f%2f0.0.0.0%3a8000%2fconfig.xml
I want to remove query string from this url. This condition should applied only for .xml extension.
Output URL should be
www.mywebsite.com/flash/module.swf
You can match a query string with a RewriteCond and %{QUERY_STRING}. If the second argument of a RewriteRule contains a query string, it will overwrite the existing query string. Clearing the query string is as easy as appending a ? to your url ;-) Alternativelly, you can use the QSD (Query String Discard) flag.
RewriteCond %{QUERY_STRING} \.xml$
RewriteRule ^flash/module\.swf$ flash/module.swf? [L]
Change the flags ([L]) to [R,L] or [R=301,L] if you want this to be an external redirect instead.