3

I am trying to use Apache rewrite to turn something like

https://www.example.com/sub/?v1=123&v2=456

into

https://www.example.com/sub/?v1=789&v2=456

i.e. changing v1 to a specific value and keeping v2. In the real case, there are more parameters.

I have

RewriteCond %{QUERY_STRING} (^|&)v1=123&v2=(\d+).*$
RewriteRule ^sub/$ sub/?v1=789&v2=%1 [NE]

which does everything except keep v2. It gets:

 https://www.example.com/sub/?v1=789&v2=

It seems like the %1 substitution did not find anything to substitute. But I can't see why not?

And I did try removing the [NE] flag, but that just causes the '&' to be lost, and does not keep the value either.

I tried this at https://htaccess.madewithlove.be/ and on our staging site, and its consistent that the substitution is not happening.

3
RewriteCond %{QUERY_STRING} (^|&)v1=123&v2=(\d+).*$
RewriteRule ^sub/$ sub/?v1=789&v2=%1 [NE]

You are using the wrong backreference in the substitution string. You have 2 capturing subgroups in the preceding condition, so you would need to use %2, not %1 as you have done. %1 is a backreference to the first captured subgroup, ie. (^|&) - which "matches" ^ (start-of-string assertion) in your example URL and will therefore appear as an empty string in the substitution string.

However, instead of changing the backreference to %2, I would also consider changing the first subpattern (alternation group) to be non-capturing instead. ie. (?:^|&). This would prevent a backreference being generated, so %1 would indeed match (\d+).

You don't appear to need the NE flag here (removing this should not "cause the '&' to be lost" in this context?). However, you may need the L flag to prevent further processing and potential conflicts with later directives.

The trailing .*$ would seem to be unnecessary in the example you posted.

So, try the following instead:

RewriteCond %{QUERY_STRING} (?:^|&)v1=123&v2=(\d+)
RewriteRule ^sub/$ sub/?v1=789&v2=%1 [L]
| improve this answer | |
1

%1 is the contents from the first set of parenthesis in your rewrite condition. You have used TWO sets of parenthesis: (^|&) and (\d+). %1 is matching the first of those which contains nothing but the "start of the expression" (^), so no characters.

You have two possible solutions:

  • Change your rewrite rule from using %1 to using %2.
  • Change your rewrite condition to use non-capturing parenthesis for the first set: (?:^|&)
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.