I asked this question earlier:
mod_rewrite: match only if no previous rules have matched?
And have been using the suggested solution with success for a while now:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} ^.+\ (/[^?\s]*)\??([^\s]*)
RewriteCond %{REQUEST_URI}?%{QUERY_STRING}<%1?%2 ^([^<]*)<\1$
RewriteRule .* /pub/dispatch.php [L]
However, we’ve since discovered that this rule fails for URLs containing single quote chars, e.g. http://example.com/don't_do_it (which is actually requested as http://example.com/don%27t_do_it)
Specifically, this is the line that’s failing to match:
RewriteCond %{REQUEST_URI}?%{QUERY_STRING}<%1?%2 ^([^<]*)<\1$
commenting it out causes the rule to match as expected, but breaks the “match only if no previous rules have matched” behavior. This is presumably related to the fact that ' is urlencoded to %27.
Here’s the relevant RewriteLog entry (for the url /asdf'asdf aka /asdf%27asdf):
RewriteCond: input='/asdf'asdf?</asdf%27asdf?' pattern='^([^<]*)<\1$' => not-matched
What I’m seeing here is that %{REQUEST_URI} is unescaped while %{QUERY_STRING} is escaped, hence the mismatch. Is there an alternative to either one of those I should be using?
Any ideas how to rewrite the above line so that it will also match lines that contain ' chars?
After beating on it for quite some time, things are looking good with: