Tadeusz Majkowski
Tadeusz Majkowski

Reputation: 642

htaccess remove percent from url string

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

Answers (1)

MrWhite
MrWhite

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

Related Questions