https://www.example.com/video.html%11
You can redirect this (and similar) URLs to replace %
with #
using something like the following mod_rewrite rule at the top of your .htaccess
file:
RewriteCond %{THE_REQUEST} ^GET\s(/video\.html)%(\d+)\s
RewriteRule . %1#%2 [NE,R=302,L]
THE_REQUEST
contains the first line of the request headers, is not %-decoded and is not affected by other rewrites.
The %1
and %2
backreferences in the substitution string contain /video.html
and the number after the %
sign respectively.
The NE
(noescape
) flag is required to prevent the #
sign being URL-encoded (as %23
) in the response and being interpreted as part of the URL-path.
HOWEVER, there are further complications with this as it depends on what ID numbers you are expecting after %
. %NN
(the first 2 digits) are obviously seen as a %-encoded character in the URL. The browser will convert some of these %-encoded characters back into the literal character before making the request, so %NN
may not reach your server. Notably, this affects the standard latin characters %61
(a) to %86
(z), numbers, uppercase letters, etc.
For example, given a request for /video.html%61
, the browser will likely convert this to /video.htmla
before making the request. In .htaccess
these will need to be checked for and converted manually, unless you have access to the server config to create a RewriteMap
for looking up the equivalent hex-codes. (The built-in escape()
function only %-encodes special characters - like the browser - so it will have no effect here.)
Aside: An additional complication on Windows servers is that any %-encoded characters that are not permitted in Windows filenames (eg. codes 0-31, which notably includes %11
(vertical tab) from your example) will result in a 403 Forbidden response before .htaccess
is able to process the request. To resolve this you would need to move this directive to the main server config (or VirtualHost) in order to process the request before it is mapped to the filesystem.