Mod_rewrite Not Working with URL Encoded Values

mod-rewriterewrite

hopefully someone can help me with this as it's driving me crazy.

I want to be able to accept URLs containing a calculation such as:

http://www.calcatraz.com/api/calc/3*3.txt

And rewrite them it this format:

http://www.calcatraz.com/calculator/api.php?a=calc&c=3*3&f=.txt

The above case works fine when I use this rewrite rule:

<IfModule mod_rewrite.c>
  Options +FollowSymLinks
  Options +Indexes
  RewriteEngine On
  RewriteRule ^api/calc/(.+)(\.(txt|sci))?$ calculator/api.php?a=calc&c=$1&f=$2 [L]
</IfModule>    

But it breaks down for URLs containing special characters, which will be URL encoded. For example 3/3 would be requested using:

http://www.calcatraz.com/api/calc/3%2F3.txt

I'd like this to rewrite, as before, to:

http://www.calcatraz.com/calculator/api.php?a=calc&c=3%2F3&f=.txt

But it doesn't – I just get an object not found error. I've played around with the 'B' flag and some others, but if they are the correct thing to use, I haven't been using them correctly!

Any pointers greatly appreciated!

Best Answer

Why even bother with a complex rewrite? PHP can handle it much easier. I was bored so I put up a simple working example.

By default Apache httpd decodes %2f (a slash) before processing the request. This has nothing to do with mod_rewrite. I have no idea why it is enabled by default. Place the following in the appropriate VirtualHost definition. Sorry, it does not work in an .htaccess file.

AllowEncodedSlashes On

.htaccess

RewriteEngine On
RewriteRule /api/calc/.* api.php

api.php

<?php

define('STRIP_URI', '/api/calc/');
define('REGEX_URI', '/^(?P<calc>.+)(?P<ext>\.(txt|sci))?$/U');

$clean_request_uri = rawurldecode(str_replace(STRIP_URI, '', $_SERVER['REQUEST_URI']));

$math = array();
preg_match(REGEX_URI, $clean_request_uri, $math);

echo $math['calc'] . "<br/>";
echo $math['ext'] . "<br/>";

Updated to fully address encoding issue.
Updated again with work-around for Apache url decoding.

Related Topic