Rewrite rule with QUERY_STRING don't work
Solution 1:
RewriteCond %{QUERY_STRING} p=(.*) RewriteRule ^(.*)/p=$ $1?page=%{QUERY_STRING} [L,QSA]
There are numerous "errors" here:
-
The
RewriteRule
pattern, ie.^(.*)/p=$
, will never match becausep=
does not occur as part of the URL-path (it is part of the query string). TheRewriteRule
pattern matches against the URL-path only, which notably excludes the query string. So, the above will do nothing for the example URL stated. -
You are using the
QUERY_STRING
server variable in place of the required URL parametervalue
in the substitution string. ButQUERY_STRING
is obviously the entire "query string", so would end up constructing a malformed query string of the form:page=p=<value>
. -
The use of the
QSA
flag results in the original query string on the request being merged with the query string you are using in the substitution string. So, this would result in&p=<value>
being appended, which is not what you required. You are looking to replace the existing query string. -
RewriteRule ^(.*)/p=$ $1?page=
- You are excluding the trailing slash from the capturing group in theRewriteRule
pattern, so this would effectively remove the trailing slash from the rewritten URL. This is different to your example. -
You appear to require an internal rewrite (no external redirect) and you are "only" changing the name of a single URL parameter. This is something you would ordinarily resolve in your application, rather than a URL rewrite in Apache. (?)
Try the following instead:
RewriteEngine On
# Internally "rewrite" the request
RewriteCond %{QUERY_STRING} ^p=([^&]*)$
RewriteRule (.*/)$ $1?page=%1 [L]
This matches any URL-path that ends in a slash (as per your example). The %1
backreference refers to the captured group in the last matched CondPattern, ie. the value of the p
URL parameter. It is assumed that p=<value>
is the only URL parameter on the request.
UPDATE: it seems not to work... if i call
localhost/list/?p=2
i simply getlocalhost/list/?p=2
Yes, the visible URL does not change, since this is an internal "rewrite" (as you appear to be requesting in your question). The URL is internally rewritten to list/?page=2
. (There is also the point that list/?page=2
is not strictly a valid end-point - it requires further rewriting, perhaps by mod_dir to form a valid request. eg list/index.php?page=2
?)
If you want the URL to visibly change then maybe you do require an external "redirect" after all? For this you need to include a slash prefix on the RewriteRule
substitution string and add the R
(redirect
) flag. For example:
# Externally "redirect" the request
RewriteCond %{QUERY_STRING} ^p=([^&]*)$
RewriteRule (.*/)$ /$1?page=%1 [R=302,L]
if i modify the rule to get
localhost/list/?p=2&?p=2
as below:RewriteEngine On RewriteCond %{QUERY_STRING} ^p=([^&]*)$ RewriteRule (.*/)$ $1&?page=%1 [L]
i get 'The requested URL
/list/&
was not found on this server.' as '?' cut the rewrite
If you request localhost/list/?p=2&?p=2
(but why?) then the above directive(s) won't do anything at all since the condition will not match.
Why did you add a &
in the RewriteRule
substitution string? (That does not make sense?) That would indeed result in a URL-path of the form /list/&
, if the rule was processed. But as stated, it wouldn't be processed for the URL you've stated?