Reputation: 6712
We have a htaccess rule like this:
RewriteRule ^(.*)/(.*)/(.*) ../app$1/scripts/api/index.php?fn=$2&$3 [L]
This works fine in most cases, however, Apache decodes the url before it arrives at this rule, so a url like beta/list/&cat=red%20%26%20blue
, is seen by htaccess as beta/list/&cat=red & blue
so we get cat='red'
and blue=null
coming into index.php
instead of cat='red & blue'
.
I've read that the workaround for this issue is to use server variables like %{REQUEST_URI}
%{THE_REQUEST}
in the htaccess rule as these are not decoded before use, but it's difficult to implement. The question mark in the RewriteRule makes everything go crazy and I can't figure out how to escape it.
Can any experts out there help me fix the rule below to behave like the one above?
RewriteCond %{REQUEST_URI} ^(.*)/(.*)/(.*)
RewriteRule . ../app%1/scripts/api/index.php?fn=%2&%3 [L]
Upvotes: 0
Views: 1456
Reputation: 19016
Indeed, the solution is to use the special server-variable called THE_REQUEST
.
From mod_rewrite documentation:
THE_REQUEST
The full HTTP request line sent by the browser to the server (e.g., "GET /index.html HTTP/1.1"). This does not include any additional headers sent by the browser. This value has not been unescaped (decoded), unlike most other variables below.
Here is how your rule should look like
# don't touch urls ending by index.php
RewriteRule index\.php$ - [L]
# user request matching /xxx/xxx/xxx (with optional query string)
RewriteCond %{THE_REQUEST} \s/([^/\?]+)/([^/\?]+)/([^\?]+)(?:\s|\?) [NC]
RewriteRule ^ ../app%1/scripts/api/index.php?fn=%2&%3 [L,QSA]
Please note that you shouldn't be using relative path for internal rewrite, which could lead to confusion. Instead, define a RewriteBase
, use an absolute path or start from the domain root with a /
.
Since you can have encoded forward slashes in your url, you need to set AllowEncodedSlashes
to NoDecode
(or On
but it's unsafe). Note also that, due to a bug, you must put this directive inside a virtual host context, even if the server config context is said to be OK (otherwise, it is simply ignored). By default, AllowEncodedSlashes
is set to Off
. So, Apache handles encoded slashes automatically by itself and refuses them, without passing the request to mod_rewrite
. See the official documentation here.
Upvotes: 1