How to redirect URL with a "?" in the middle that is not a query - .htaccess

How can I redirect a URL that has a "?" in the middle of it (not like a typical query string)?
The problem URL:
https://example.com/michigan/jobs/?/jobs/
I need to rewrite or redirect it to:
https://example.com/michigan/jobs/
I have tried all of these, and none of them work (no change):
1. Redirect 301 https://example.com/michigan/jobs/?/jobs/ https://example.com/michigan/jobs/
2. Redirect 301 /michigan/jobs/?/jobs/ /michigan/jobs/
3. RedirectMatch 302 ^/michigan/jobs/?/jobs/ /michigan/jobs/
4. RewriteRule ^/michigan/jobs/?/jobs/$ /michigan/jobs/ [R=301,L]
RewriteRule ^michigan/jobs/?/jobs /michigan/jobs/
I've tried a bunch of different "generators" but they don't seem to detect the random "?" in the middle of things.
What would be the correct redirect or rewrite rule to handle this?

not like a typical query string
Although that IS a query string, just like any other. Anything after the first ? is a query string, whether that is the intention or not is another matter. So, in your example /jobs/ is the query string.
The Redirect, RedirectMatch and RewriteRule directives all match against the URL-path only, which notably excludes the query string.
To match the query string, you need to use mod_rewrite and an additional RewriteCond directive (a "condition") that compares against the QUERY_STRING server variable, together with a RewriteRule.
For example:
RewriteEngine On
# Removes the query string from "/michigan/jobs/?/jobs/"
RewriteCond %{QUERY_STRING} ^/jobs/$
RewriteRule ^michigan/jobs/$ /$0 [QSD,R=301,L]
The $0 backreference contains the full match from the RewriteRule pattern - basically the full URL-path. This just saves repetition.
The QSD (Query String Discard) flag then discards the original query string from the redirect response, otherwise it is passed through by default.
Note that the URL-path matched by the RewriteRule pattern does not start with a slash.
Test first with a 302 (temporary) redirect to avoid potential caching issues.

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]

remove all querystring from any url [duplicate]

Have been trying to write a redirect rule with query string but did not succeed.
I have the URL example.com/blog/?page=1 or example.com/blog/?hello, so it does not really matter what goes in the query string. How do I write a Redirect rule, so that it cuts the query string and redirects to the URL before the query string. For example, both of those URLs have to redirect to example.com/blog/ so that URL does not contain any query string.
I was trying
RewriteRule ^blog/?$ blog/ [R=301,L,NE] but got redirected to 404 page.
Also tried
RewriteRule ^blog/?$ /blog/ [R=301,L,NE] and got the message that page is not working, 'URL' redirected you too many times.
BTW, technology I am using is Gatsby with htaccess plugin.
To remove the query string you first need to check that there is a query string to remove, otherwise, it should do nothing.
For example, to remove the query string from /blog/?<query-string> you would do something like this:
RewriteCond %{QUERY_STRING} .
RewriteRule ^(blog)/?$ /$1/ [QSD,R=302,L]
This matches the URL-path blog/ (trailing slash optional) and redirects to /blog/ (with a trailing slash). Your example URL includes the trailing slash, but your regex appears to suggest the trailing slash is optional?
The preceding condition (RewriteCond directive) checks the QUERY_STRING server variable to make sure this is non-empty (ie. it matches a single character, denoted by the dot).
The $1 backreference in the substitution string contains the value from the captured group in the preceding RewriteRule pattern. ie. "blog" in this example. This simply saves repetition. You could just as easily write RewriteRule ^blog/?$ /blog/ [QSD,R,L] instead.
The QSD (Query String Discard) flag removes the original query string from the redirected response, otherwise, this would be passed through by default (which would create a redirect-loop).
If the request does not contain a query string then this rule does nothing (since the condition will fail).
If this is intended to be permanent then change the 302 (temporary) redirect to 301 (permanent), but only once you have confirmed this works as intended. 301s are cached persistently by the browser so can make testing problematic.
A look at your existing rules:
was trying RewriteRule ^blog/?$ blog/ [R=301,L,NE] but got redirected to 404 page.
By default, the relative substitution string (ie. blog/) is seen as relative to the directory that contains the .htaccess file and this "directory-prefix" is then prefixed back to the relative URL, so this will (by default) result in a malformed redirect of the form https://example.com/path/to/public_html/blog/.
Also tried RewriteRule ^blog/?$ /blog/ [R=301,L,NE] and got message that page is not working, 'url' redirected you too many times.
This is not checking for (or removing) the query string so this is basically just redirecting to itself - an endless redirect-loop.
Remove any query string from any URL
What rule do i write, to remove query string from any URL.
Modify the RewriteRule pattern to match any URL and redirect to the same. For example:
RewriteCond %{QUERY_STRING} .
RewriteRule (.*) /$1 [QSD,R=302,L]
This needs to go at the top of the root .htaccess file before any existing rewrites.
If the .htaccess file is in a subdirectory (not the root) then you will need to do something like the following instead, since the $1 backreference (as used above) won't contain the complete root-relative URL-path.
RewriteCond %{QUERY_STRING} .
RewriteRule ^ %{REQUEST_URI} [QSD,R=302,L]

Redirect rule to remove query string from URL

Have been trying to write a redirect rule with query string but did not succeed.
I have the URL example.com/blog/?page=1 or example.com/blog/?hello, so it does not really matter what goes in the query string. How do I write a Redirect rule, so that it cuts the query string and redirects to the URL before the query string. For example, both of those URLs have to redirect to example.com/blog/ so that URL does not contain any query string.
I was trying
RewriteRule ^blog/?$ blog/ [R=301,L,NE] but got redirected to 404 page.
Also tried
RewriteRule ^blog/?$ /blog/ [R=301,L,NE] and got the message that page is not working, 'URL' redirected you too many times.
BTW, technology I am using is Gatsby with htaccess plugin.
To remove the query string you first need to check that there is a query string to remove, otherwise, it should do nothing.
For example, to remove the query string from /blog/?<query-string> you would do something like this:
RewriteCond %{QUERY_STRING} .
RewriteRule ^(blog)/?$ /$1/ [QSD,R=302,L]
This matches the URL-path blog/ (trailing slash optional) and redirects to /blog/ (with a trailing slash). Your example URL includes the trailing slash, but your regex appears to suggest the trailing slash is optional?
The preceding condition (RewriteCond directive) checks the QUERY_STRING server variable to make sure this is non-empty (ie. it matches a single character, denoted by the dot).
The $1 backreference in the substitution string contains the value from the captured group in the preceding RewriteRule pattern. ie. "blog" in this example. This simply saves repetition. You could just as easily write RewriteRule ^blog/?$ /blog/ [QSD,R,L] instead.
The QSD (Query String Discard) flag removes the original query string from the redirected response, otherwise, this would be passed through by default (which would create a redirect-loop).
If the request does not contain a query string then this rule does nothing (since the condition will fail).
If this is intended to be permanent then change the 302 (temporary) redirect to 301 (permanent), but only once you have confirmed this works as intended. 301s are cached persistently by the browser so can make testing problematic.
A look at your existing rules:
was trying RewriteRule ^blog/?$ blog/ [R=301,L,NE] but got redirected to 404 page.
By default, the relative substitution string (ie. blog/) is seen as relative to the directory that contains the .htaccess file and this "directory-prefix" is then prefixed back to the relative URL, so this will (by default) result in a malformed redirect of the form https://example.com/path/to/public_html/blog/.
Also tried RewriteRule ^blog/?$ /blog/ [R=301,L,NE] and got message that page is not working, 'url' redirected you too many times.
This is not checking for (or removing) the query string so this is basically just redirecting to itself - an endless redirect-loop.
Remove any query string from any URL
What rule do i write, to remove query string from any URL.
Modify the RewriteRule pattern to match any URL and redirect to the same. For example:
RewriteCond %{QUERY_STRING} .
RewriteRule (.*) /$1 [QSD,R=302,L]
This needs to go at the top of the root .htaccess file before any existing rewrites.
If the .htaccess file is in a subdirectory (not the root) then you will need to do something like the following instead, since the $1 backreference (as used above) won't contain the complete root-relative URL-path.
RewriteCond %{QUERY_STRING} .
RewriteRule ^ %{REQUEST_URI} [QSD,R=302,L]

Redirect URL with query string to new "pretty" URL to avoid duplicate content

What the best .htaccess rewrite code to force URL like this one
https://www.example.com/index.php?page=report/tinytoes_mothercare
to that?
https://www.example.com/report/tinytoes_mothercare
My web site already resolve https://www.example.com/report/tinytoes_mothercare, so I want to avoid any duplicate contents with the ugly and bad URL above.
You can do something like the following at the top of your .htaccess file, before the existing rewrite (that "resolves" the pretty URL) to redirect the old URL with a query string to your new pretty URL.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^page=([\w/-]*)
RewriteRule ^index\.php$ /%1 [QSD,R=302,L]
The first condition that checks against the REDIRECT_STATUS environment variable ensures we don't get a redirect loop by redirecting the rewritten URL. REDIRECT_STATUS is empty on the initial request, so only redirects direct requests from the client.
The second condition gets the necessary value from the query string page URL parameter. This matches characters a-z, A-Z, 0-9, _ (underscore), / (slash) and - (hyphen) - as in your example URL. If you need to match more variation then the character class will need to be expanded. This value is then used in the RewriteRule substitution string using the %1 backreference.
Note that this is a 302 (temporary) redirect. Only change to a 301 (permanent) when you are sure it works OK, in order to avoid caching issues.

.htaccess redirect with query string on new website structure

I have changed the website URL structure and I want to redirect my users.
Need to redirect from:
https://example.com/find?q=batman
To
https://example.com/search?query=batman
where "batman" is the search phrase.
The problem for me, is how to change
q to query after ?
Something like that, it does not work
RewriteRule ^find?q=[^/] /search?query=[^/] [R=302,L]
The RewriteRule pattern matches against the URL-path only - this notably excludes the query string.
Instead, you need to use a RewriteCond directive to check the QUERY_STRING server variable and capture the remainder of the query string after the q=.
For example:
RewriteCond %{QUERY_STRING} ^q=(.*)
RewriteRule ^find$ /search?query=%1 [R=302,L]
%1 is a backreference to the captured group in the last matched CondPattern. ie. (.*) - the value of the q URL parameter and remainder of the query string.
Change the 302 (temporary) redirect to 301 (permanent) only once you have confirmed that it works OK - to avoid caching issues.

Resources