Why is query string repeated in rewrite URL? - .htaccess

I have these rewrites. The first (for gallery) works as expected. The second (for photo) works but the query string is repeated. So it forwards to: http://www.domain.com/photo-TheID?id=TheID
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /gallery\.php\?set=([^/]*)\ HTTP/
RewriteRule ^gallery\.php$ http://www.domain.com/gallery?set=%1 [R=301,L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /photo\.php\?id=([^/]*)\ HTTP/
RewriteRule ^photo\.php$ http://www.domain.com/photo-%1 [R=301,L]
However, if I add ? to the end of the rewriterule making it
RewriteRule ^photo\.php$ http://www.domain.com/photo-%1? [R=301,L]
It then works as expected forwarding to: http://www.domain.com/photo-TheID
My question is why is that query string being repeated without the "?" at the end? It's very confusing to me since the first rewrite (for gallery) does not have the ? yet it does not repeat the query string. If I add ? to the end of the gallery rewriterule it adds "%3f" to the end of the url.

Because it is appended automatically unless you place a trailing question mark in the substitution URL, provided it doesn't hold a new query string.
"When you want to erase an existing query string, end the substitution string with just a question mark".
Check the title Modifying the Query String in this Apache link.
Your question:
It's very confusing to me since the first rewrite (for gallery) does not have the ?
The reason is the first rewrite rule:
RewriteRule ^gallery\.php$ http://www.domain.com/gallery?set=%1
creates a new query string and in that case the incoming query string is not appended automatically unless you explicitly do it with the QSA flag.

Related

Redirect a URL in .htaccess, but keep the query string

I want to redirect a URL in .htaccess, but want to keep the (dynamic) parameters from the query string at the end of the URL (e.g. ?id=1660, ?id=1661, etc.)
E.g.
https://mywebsite.example/service/viewinvoice.php?id=1660
I want to redirect it to:
https://mywebsite.example/whmcs-bridge/?ccce=viewinvoice.php?id=1660
So basically: https://mywebsite.example/service/viewinvoice.php?id=... needs to be redirected to https://mywebsite.example/whmcs-bridge/?ccce=viewinvoice.php?id=...
I tried this below, without any success
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)/service/viewinvoice.php?id= [NC]
RewriteRule ^/?$ /whmcs-bridge/?ccce=viewinvoice.php [L,R=301]
I think this is not the right solution.
Does someone has suggestions?
You need to use the QSA (Query String Append) flag on your rewrite rule. From the documentation:
When the replacement URI contains a query string, the default behavior of RewriteRule is to discard the existing query string, and replace it with the newly generated one. Using the [QSA] flag causes the query strings to be combined.
From your example URLs, you don't need to match the query string in a rewrite condition. You are matching the URL path which is done as the first part of the rewrite rule itself.
Your rule should be:
RewriteEngine On
RewriteRule ^/?service/viewinvoice\.php$ /whmcs-bridge/?ccce=viewinvoice.php [L,R=301,QSA]

Sanitize query parameters in the URL with htaccess

Is there a way with mod_rewrite to sanitize an URL of this type:
https://www.example.com/blabla/?&param1=1&param2=2
to
https://www.example.com/blabla/?param1=1&param2=2
Thank you
RewriteCond %{QUERY_STRING} ^&(.*)
RewriteRule ^(.*)$ /$1?%1 [R=301,L]
That should basically do it. The RewriteCond matches on any query string that starts with &, and simply captures the rest.
And then you simply insert the back reference to that "rest" into the substitution URL, using %1.
Edit: Pattern changed to (.*) to capture all URL paths; back reference $1 inserted into substitution URL.

Htaccess 301 redirect with query string params

This is so elementary that you have to ask why it is so complex to implement.
Simply need to redirect one url to another on the same domain, the url contains query string aparams though:
I tried:
RewriteRule ^article.php?section=exclusive&id=543 articles/view/4639 [R=301,L]
I get page cannot be found - the redirect is not happening. I have other re-directs in the same htaccess which work. The query string params are causing problems, and escaping them also does not help.
Note the id's of the two urls are not the same and therefore I don't want a clever re-write rule which converts from one url to another with the query strings mapped to new params. I just want a fast and dirty mapping from A to B.
UPDATE
I tried this it redirects but it is adding my old query string to the end of the new url. How can I prevent that?
RewriteCond %{REQUEST_URI} ^/article\.php$
RewriteCond %{QUERY_STRING} ^section=exclusive
RewriteRule ^$ http://www.onlinegooner.com/articles/view/3000 [R=301,L]
Input url is: mydomain.com/article.php?section=exclusive
You may use this rule:
RewriteCond %{QUERY_STRING} ^section=exclusive [NC]
RewriteRule ^article\.php$ /articles/view/3000? [R=301,L,NC]
? in the target will strip off previous query string.

.htaccess redirect question mark with no parameters

I have several URLs with question marks that need to be removed. For example, I need to redirect this URL:
http://example.net/?/services
To this URL:
http://example.net/services
I have many more like this, so I would like something that can catch everything with the question mark and properly redirect it. Many of the answers I found were trying to use QUERY_STRING as the condition for the rewrite, but without parameters this does not help. After some digging I found a RewiteCond that works, but the RewriteRule redirects to the homepage, rather than the URL without the question mark. What I have currently is this:
# Remove question mark from string
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(index\.php)?\?([^&\ ]+)
RewriteRule ^ /%1? [L,R=301]
# Removes index.php from ExpressionEngine URLs
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
# Directs all EE web requests through the site index file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1 [L]
The first block is the rewrite that I have so far, and the next two are for the CMS url routing. What seems to be happening is that my rewrite in the first block is not keeping the rest of the url. I have tried several combinations and can't seem to figure out how to keep the rest of the url intact.
Many of the answers I found were trying to use QUERY_STRING as the condition for the rewrite, but without parameters this does not help.
Yes, this is exactly what the first URL, with a question mark, contains. So, I'm not sure why "this does not help"? In the URL http://example.net/?/services, /services is the query string. Whether there are key/value pairs (ie. "parameters") is irrelevant.
To redirect URLs of the form http://example.net/?/services, that consist of no URL-path and only a query string, try something like:
# Remove question mark from string
RewriteCond %{QUERY_STRING} ^/(.+)
RewriteRule ^$ /%1? [R,L]
%1 is a backreference to the captured group in the last matched CondPattern (ie. (.+), which captures services). This assumes that the query string (after the ?) always starts with a slash, as in your example. (Incidentally, this is also what your front controller is doing, in reverse, so I assume it must be correct.)
The trailing ? on the substitution removes the original query string from the request.
Make sure you clear your browser cache, as any earlier/erroneous 301s will have been cached by the browser.
If this is intended to be a permanent (301) redirect then change R to R=301, but only when you are sure it's working OK.

Mod Rewrite Appending Query String Parameters, Not Replacing

I am trying to generate an external redirect that involves a few specific tasks.
If specific query string value is found in the URL, redirect.
If redirected, replace one of the query string parameter names but not its value.
If #1 is false, then ignore rewrite and proceed
Example: I have the url http://foobar.com/?a=123&b=456&c=blah
First, if parameter c = blah, redirect to http://barfoo.com/
Second, replace a with x parameter so the final URL is http://barfoo.com/?x=123&b=456&c=blah
Below is my best guess so far after researching on http://mod-rewrite-cheatsheet.com/ and Hidden features of mod_rewrite
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.foobar\.com$ [NC]
RewriteCond %{QUERY_STRING} ^a=(.*)&b=(.*)&c=blah$ [NC]
RewriteRule ^(.*)$ http://barfoo.com/?x=%1&b=%2&c=blah [NC,L,QSA,R=301]
However, the URL is appending the query string, not replacing.
I get redirected to http://barfoo.com/?x=123&b=456&c=blah&a=123&b=456&c=blah
smacks forehead
Removing QSA from the flags solved the issue. QSA means "append the existing query string to the current rewrite rule." It ignores whatever new query string parameters you are adding.
I thought it was needed to have query string parameters exist for the rewrite rule itself.
RewriteRule ^(.*)$ http://barfoo.com/?x=%1&b=%2&c=blah [NC,L,R=301]

Resources