How do you prevent mod_rewrite from decoding a string in the path?

Mike asked:

I’m trying to create a restful API using mod_rewrite.

I have the rule:

RewriteRule v2/(.*)$ v1/index.php?request=$1 [QSA,NC,L]

However the path could contain base64 encoded strings (i.e. can have + or /) and they are being decoded before it gets to PHP.

For example, if I go to


PHP gets $_REQUEST['request'] as cards/9VwQLli f0ogFl19AVRFLuztbp8cP0rYCgXBu3H9 Dc=Be'.

And to make things worse, if I add a slash in there (e.g. 9VwQLli%2Bf0ogFl19AVRFLuztbp8c%2FP0rYCgXBu3H9%2BDc%3DBe – the %2F is the slash) I get a 404.

How can I prevent this from happening?

Note: I tried the B and NE flags but they didn’t have any effect. I suppose as a hack I could just convert all + characters to _ and all / to -, or maybe even double url encoding it, but I was wondering if there was a better way.

My answer:

You don’t. The web server is allowed to decode percent-encoded characters which don’t decode to special characters before applying rewrite rules, and is allowed to decode the remainder of percent-encoded characters before passing the data to your web application. (See RFC 3986.)

What you should be doing is applying the front controller pattern in your web application, and handling all the percent decoding (and request routing) yourself. In this case you will simply redirect all requests that don’t match a file or directory to /index.php and then read the URL out of $_SERVER['REQUEST_URI']. This is how major PHP-based web apps like WordPress and MediaWiki handle this.

View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.