mod_rewrite & PHP: How to match urlencoded plus sign (+ = %2B)

I ran into trouble when trying to pass a urlencode()‘ed plus sign into a web address being processed by mod_rewrite.

$url = 'http://www.server.com/browsealpha/name+has+plus+in+it/';
$url = urlencode($url); // http://www.server.com/browsealpha/name%2Bhas%2Bplus%2Bin%2Bit/

This $url variable gets echo()‘d as a link in a page, so once it’s clicked and loaded in the browser, I then needed mod_rewrite to translate that to the actual URL, which is:

http://www.server.com/browsealpha.php?name=name%2Bhas%2Bplus%2Bin%2Bit

Here is the RewriteRule I was using to match:

# match any name containing any combination of letters, numbers, and the % sign (to match urlencoded URLs)
RewriteRule ^browsealpha/([%\w]*)/?$ /browsealpha.php?name=$1 [QSA,L]

This rule should match http://www.server.com/browsealpha/name%2Bhas%2Bplus%2Bin%2Bit/ but for some reason it wouldn’t work. After hours of frustration, I found a few threads mentioning the need to urlencode() the string twice, like so:

urlencode(urlencode($variable));

IT WORKS!!! Apparently this is because mod_rewrite automatically decodes the urlencoded URL, so if you pass in %2B, PHP sees it as %2B0. If you double encode, mod_rewrite decodes the first one, and PHP receives the second one (which is now %2B, which is what we want).

—————-
Now playing: Autechre – 444
via FoxyTunes

5 responses to “mod_rewrite & PHP: How to match urlencoded plus sign (+ = %2B)”

  1. Mickey says:

    Thanks man,

    you saved my day.

  2. Orhan says:

    Thanks dude, thanks to you i can stop now for looking to the solution/problem. This was just what I needed and it worked!

  3. thegap says:

    Great, works fine for me 🙂

    I just searched a long time until i found your page.

  4. Lauri says:

    Sweet! I had this problem with Javascript/PHP communication, and your post made me try: decodeURIComponent(decodeURIComponent(queryString)) – that did it! Thanks a lot

  5. Lauri says:

    Oops – encodeURIComponent(encodeURIComponent(queryString)) is what I meant