I suspect that you're using PATH_INFO
to handle your CodeIgniter requests. Consequently, your .htaccess
file contains a rule set that looks similar to this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php/$0 [L]
When mod_rewrite
tests your URLs, they have already been decoded to their natural character format, so in this case %25
has become just %
. When you apply this rule, the backreference actually contains the literal text somepath/morestuff/ohno%foobar
, which is not re-encoded by default. Apache has no idea what that %
is doing in your request path to /index.php/somepath/morestuff/ohno%foobar
and chokes, giving you that error.
If you're running Apache 2.2, mod_rewrite
added the B
flag for this purpose, allowing you to automatically escape backreferences rewritten to your URL. Adding it to your current flag list should fix the problem in that case:
RewriteRule ^.*$ index.php/$0 [B,L]
There's also an escape
RewriteMap
that's available as an internal map in previous Apache versions of mod_rewrite
, but unfortunately this map has to be enabled at the server or virtual server configuration level, so may not be available if you're running your site on shared hosting. It does the same thing, though a bit more deliberately.
In your server/virtual server configuration:
RewriteMap escape int:escape
Then, wherever you define your rules:
RewriteRule ^.*$ index.php/${escape:$0} [L]
Keep in mind that CodeIgniter doesn't need to use PATH_INFO
to get the request information, and using REQUEST_URI
is perfectly acceptable here if you aren't using mod_rewrite
to do any other transformations (and would avoid this headache altogether). I think by default CodeIgniter is set to get the request from AUTO
(assuming I haven't gotten my frameworks mixed up), so simply not rewriting the request to the URL with path info would be enough to make that change.