Why is my Apache RewriteRule removing hex codes from the target url query string?

I have an apache rewrite rule:

RewriteRule ^/xy[/]{0,1}$ https://www.example.com/path/file.php?utm_source=Billboard&utm_medium=Print&utm_campaign=MyOrg%20Promo&utm_term=2020FA&utm_context=XY%2C%20border%20state%20abbreviation%20redirect [R]

But my target url is actually becoming:

https://www.example.com/path/file.php?utm_source=Billboard&utm_medium=Print&utm_campaign=MyOrg0Promo&utm_term=2020FA&utm_context=XYC0border0state0abbreviation0redirect

So, it is stripping out the %2 part of the hex codes in the query string of the target.

I have tried setting the PT, B, NE, QSD, & BNP flags. I'm on Apache 2.4.6(CentOS), and the BNP flag isn't supported there.

How can I get Apache to leave those codes alone?


Solution 1:

Because %2 is a backreference in mod_rewrite substitution strings, that would otherwise refer back to the 2nd captured subpattern in the last matched CondPattern. There is none in the example you posted, so this is replaced with an empty string - so it looks like it is simply "stripped".

For any sequent of %n (where n is 0-9), you need to backslash escape the % to negate its special meaning. ie. \%20

Or, use + instead of %20 to escape literal spaces in the query string.

You will need the NE flag on the RewriteRule to prevent the query string being doubly escaped. (And you should probably be using the L flag as well.)