Reputation: 642
I'm trying to remove a percent sign from the URL using .htaccess
. When I add %
on end of the URL I get request code 400.
Here is my .htaccess
code:
# NON-WWW HTTPS
RewriteEngine On
RewriteBase /
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
### NO SLASH ON URL END
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
### FORCE TO LOAD EXISTING FILES
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
### URL AS MAIN STRING
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
I found some similary solution here htaccess to escape percent (%) from URL but its not work in my case.
When I add line in the end:
RewriteRule .* index.php?url=$1 [PT,B]
.htaccess
didn't load any external files like CSS & images.
Upvotes: 2
Views: 725
Reputation: 45829
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.
Upvotes: 1