2

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.

MrWhite
  • 43,179
  • 8
  • 60
  • 84
Tadeusz Majkowski
  • 612
  • 2
  • 8
  • 26

1 Answers1

1

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.

MrWhite
  • 43,179
  • 8
  • 60
  • 84
  • Thank You :) I use .htaccess ErrorDocument 400 /errdocs/e404.php redirect, but still have an error 400 on my screen. When I fix it then use your code. – Tadeusz Majkowski Sep 20 '18 at 11:29
  • Have you created the `/errdocs/e404.php` PHP file and added the above PHP code? – MrWhite Sep 20 '18 at 11:31
  • I used your example and still nothing :( at the top of document just like you write – Tadeusz Majkowski Sep 20 '18 at 11:34
  • Can you add the exact output you are seeing to your question. Thanks. (You may need to add an exception to allow the error document to be served.) – MrWhite Sep 20 '18 at 11:50
  • Nothing new, looking forward for solution. Thank you for your time i will place here comment if find something interesting :) – Tadeusz Majkowski Sep 20 '18 at 12:03
  • "Nothing new" - what does that mean? I can't see the response you are seeing. All you've stated is that there is a "request code 400" - but what do you actually see? The 400 output you are seeing is important in answering this question. For example, are you seeing the contents of your error document? Are you seeing a _system generated_ 400 response from Apache? Is it unable to find the custom error document for some reason? Is there a conflict with your existing directives (when serving the error document)? The response you see in the browser could answer these questions. – MrWhite Sep 20 '18 at 12:08
  • OK, When i post my question i get code 400 from server. Its page with text error 400. I add this to my .htaccess ErrorDocument 400 /errdocs/e404.php and create file on spec directory. But the error was the same. If you look at my .htaccess and add at last line RewriteRule ^(.+)$ index.php?url=$1 [PT,B] it will work as i need. It reduce % in url string but now its not loading content like CSS & images :) – Tadeusz Majkowski Sep 20 '18 at 12:19
  • 1
    Now its working with your solution. I just remove some trash from server :) – Tadeusz Majkowski Sep 20 '18 at 16:20
  • Thank you once again :) – Tadeusz Majkowski Sep 20 '18 at 16:25