htaccess redirect all urls with question mark parameter to without
I checked a lot, for my question. there are some close, but none that would solve my problem.
I need to permanently redirect ALL URLs that end in this:
?mode=list
AND
?mode=grid
to without (remove the question mark and what is after it)
Example:
example.com/random-url-here?mode=grid redirect to example.com/random-url-here
AND
example.com/whatever-url-here?mode=list redirect to example.com/random-url-here
I tried this:
RewriteEngine on
RewriteRule (.*)$^mode=list $1
RewriteRule (.*)$^mode=grid $1
and this
RewriteEngine on
RewriteRule (.*)$^mode=list $1 [L,R=301]
RewriteRule (.*)$^mode=grid $1 [L,R=301]
But it doesn't work. Clearly, I don't understand how this works. Please help.
Thank you
Solution 1:
example.com/random-url-here?mode=grid
The part of the URL after the first ?
(ie. mode=grid
in this example) is called the query string.
RewriteRule (.*)$^mode=list $1 [L,R=301]
The RewriteRule
directive takes up to 3 arguments:
RewriteRule pattern substitution [flags]
The pattern (first argument) to the RewriteRule
directive is a regular expression (regex) that matches against the requested URL-path only, which notably excludes the query string. Therefore you can't match the query string using the RewriteRule
directive.
To match the query string you need to use an additional RewriteCond
(condition) directive and check against the QUERY_STRING
server variable. RewriteCond
directives apply conditions to the RewriteRule
directive that follows.
However, the regex (.*)$^mode=list
(apart from trying to match the query string) will never match in this context. $
asserts the end-of-line and ^
asserts the start-of-line - so this will always fail.
In your example above, the $1
backreference (in the substitution string) is attempting to match the URL-path. However, this URL-path (in a directory context, ie. .htaccess
) does not start with a slash (ie. it's relative), so will result in a malformed redirect unless you also have a RewriteBase
directive defined elsewhere in your .htaccess
file. A relative substitution string is seen as a filesystem path relative to the directory that contains the .htaccess
file.
If you omit the R
(redirect
) flag in this context (as in your first example) then it will try to internally rewrite the request (not externally redirect), so the visible URL will not change.
Try the following instead, near the top of your root .htaccess
file:
RewriteEngine On
RewriteCond %{QUERY_STRING} ^mode=(list|grid)$
RewriteRule (.*) /$1 [QSD,R=302,L]
The above states... for all URLs (.*)
that have a query string of mode=list
or mode=grid
(exactly) then redirect to the same URL-path and discard the query string (QSD
- Query String Discard). The QSD
is new to Apache 2.4 (which I assume you are using). If you omit the QSD
flag then you will get a redirect loop (since the query string will be re-appended to the redirected URL).
Note that the above matches the query string exactly (as in your examples). If there are any other URL parameters in the query string or the case is different then it will fail to match.
Note that this is a 302 (temporary) redirect. Only change it to a 301 (permanent) - if that is the intention - when you have confirmed that it works OK. 301s are cached persistently by the browser so can make testing problematic.
Reference:
- https://httpd.apache.org/docs/2.4/rewrite/intro.html
- https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html