When I add %
on end of the URL I get request code 400.
The 400 "Bad Request" is triggered by Apache before .htaccess
/mod_rewrite is able to process the URL. Since an arbitrary %
in the URL is a wholly invalid URL (it would itself need to be %-encoded as %25
).
If you specifically need to correct these URLs then you could create a custom 400 ErrorDocument
and in that error document (in PHP) check the requested URL for %
, remove them and redirect.
For example, at the top of your .htaccess
file:
ErrorDocument 400 /errdocs/e404.php
Then in /errdocs/e404.php
you can check the $_SERVER['REDIRECT_URL']
variable (and optionally $_SERVER['REDIRECT_QUERY_STRING']
- depending on where in the URL you are checking for %
) for arbitrary %
and 301 redirect (overriding the 400 status).
For example, within your e404.php
error document:
// Since the REDIRECT_URL value is already %-decoded we can simply remove
// any remaining "%" if none are meant to be in the URL (even if correctly encoded as %25)
if (strstr($_SERVER['REDIRECT_URL'], '%')) {
$cleanUrl = str_replace('%', '', $_SERVER['REDIRECT_URL']);
// Append back the query string (if any)
if (isset($_SERVER['REDIRECT_QUERY_STRING'])) {
$cleanUrl .= '?'.$_SERVER['REDIRECT_QUERY_STRING'];
}
// Redirect to clean URL
header('Location: http://'.$_SERVER['HTTP_HOST'].$cleanUrl,true,302);
exit;
}
As noted in the code comment above, this removes any %
that remain in the URL-path, even if correctly encoded. This does not currently check the query string, but you could apply the same process to REDIRECT_QUERY_STRING
if you wish.
Test with 302 (temporary) redirect and only change it to 301 (permanent) when you are sure it's working OK.