Home > Blockchain >  Removing file extensions using .htaccess causes errors
Removing file extensions using .htaccess causes errors

Time:09-25

Earlier today, I was trying to remove the php file extension when people visit my website using .htaccess. (Sort of like https://tecadmin.net/remove-file-extension-from-url-using-htaccess/) Below is my .htaccess file:

#Remove php file extensions
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.] )$ $1.php [NC,L]

RewriteEngine on 
RewriteCond %{THE_REQUEST} /([^.] )\.php [NC]
RewriteRule ^ /%1 [NC,L,R]

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_URI}.php [NC,L]

The code seems to be doing its job, but I quickly noticed a problem. http://example.com/page and http://example.com/page.php works perfectly fine, but when I visit http://example.com/page/, the server returns an internal server error. (500)

I tried looking online on how to fix this, but I came up empty. Does anyone know how to fix this problem?

CodePudding user response:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.] )$ $1.php [NC,L]

RewriteEngine on 
RewriteCond %{THE_REQUEST} /([^.] )\.php [NC]
RewriteRule ^ /%1 [NC,L,R]

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_URI}.php [NC,L]

Your first and last rules are doing the same sort of thing (appending the .php extension via an internal rewrite), however, they are doing it slightly differently and arguably incorrectly. And you certainly don't need both.

The 500 error when requesting /page/ is caused by a rewrite-loop. The first rule rewrites the request to /page/.php. The last rule then rewrites the request a 2nd time to /page/.php.php and then again to /page/.php.php.php etc. etc. Because REQUEST_FILENAME is /page in all cases and so %{REQUEST_FILENAME}.php (in the condition) is not necessarily the same as %{REQUEST_URI}.php (the URL being rewritten to).

Try the following instead:

Options -MultiViews

RewriteEngine On

# Remove php file extensions

RewriteCond %{THE_REQUEST} \s/([^.] )\.php [NC]
RewriteRule ^ /%1 [R=301,L]

RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.] )$ $1.php [L]

The redirect that removes the .php extension should probably be a 301 (permanent) redirect, once you have confirmed that this works as intended.

The NC flags on the RewriteRule directives were superfluous.

There's no need to backslash-escape literal dots when used inside a regex character class. The dots carry no special meaning here. So, [^.] is the same as [^\.]. (Although you escaped one and not the other.)

This now checks for the same file %{DOCUMENT_ROOT}/$1.php that is being rewritten to in the RewriteRule substitution string, ie. $1.php.

NB: I've explicitly disabled MultiViews to ensure that these directives are not overridden by mod_negotiation.

This will now result in a 404 should /page/ (with a trailing slash) be requested. If this should return the same as /page then this should be implemented as an additional redirect, to remove the trailing slash.

  • Related