1

I've a problem with some rewrite rules for my URL, I'm using this rule to remove .php from the URL of my website

Options +SymLinksIfOwnerMatch 

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]

The problem is that when added a trailing slash at the end, the website gives back an error.

Example:

example.com/test/ gives back an error

I do think that's because it rewrites it like example.com/test/.php, I do not know how to properly solve that

MrWhite
  • 43,179
  • 8
  • 60
  • 84
thenewbie
  • 21
  • 4
  • I assume these directives are in `.htaccess`? – MrWhite Oct 30 '21 at 10:55
  • And would you also care to say _what_ error you receive back? – arkascha Oct 30 '21 at 12:18
  • @arkascha, as MrWhite said, I get an Interna server error, that's why I added the rule to redirect to the index.php when getting these errors, I know that's useless but I added it only to hide the Internal Server Error page. – thenewbie Oct 31 '21 at 01:07
  • @MrWhite, yes the directives are in .htaccess – thenewbie Oct 31 '21 at 01:07
  • An internal server error" is only the informtion the server hands out to people using the website. Such error does not contain any details, because those are sensitive data. You as the operator need to look into your http server's error log file. That is where the http server logs all details of that specific issue. Typically that is what is required to solve the issue. – arkascha Oct 31 '21 at 09:35
  • @thenewbie So, how did you get on with my answer? – MrWhite Oct 31 '21 at 12:00
  • @MrWhite I used your rule to avoid the server error, right now I get back the 404 page, thank you, one last thing I'd like to know if is it possible to make URLs that end .php also with the trailing slash, for example, https://example.com/url.php into https://example.com/url/ – thenewbie Nov 30 '21 at 01:55

1 Answers1

1

I do think that's because it rewrites it like example.com/test/.php

Yes, that is what's happening. But it will do this repeatedly (causing a rewrite-loop) until the server "breaks" with a 500 Internal Server Error.

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php

The "problem" with this is that you aren't necessarily testing the existence of the same file in the RewriteCond directive that you are rewriting to in the RewriteRule directive.

So, this will cause an error (rewrite-loop / 500 Internal Server Error) when appending a slash because REQUEST_FILENAME is /abs/path/to/test (the resolved filesystem path) and /abs/path/to/test.php exists, but it internally rewrites the request to test/.php because $1 is test/ (captured from the URL-path). It will do this repeatedly until the server aborts with an error.

You need to make sure you are always testing the same thing in the condition as you are rewriting to later.

See my answer to the following question on ServerFault with a detailed explanation of this behaviour: https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error

Additional points...

  • You are missing the L flag, so processing continues on to the next rule.
  • The first condition that checks the request does not map to a directory is not required, since you are already checking that <whatever>.php exists as a file.
  • Minor point, but there is no need to backslash-escape a literal dot in the TestString (1st argument to the RewriteCond directive) - this is not a regex.

For example, use the following instead:

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

Now, %{DOCUMENT_ROOT}/$1.php in the RewriteCond directive refers to the same string/file as $1.php in the substitution string.

So, when you request /test/, it will now be testing /abs/path/to/test/.php in the RewriteCond directive, which doesn't exist, so nothing happens (results in a 404). /test and test/ are, after all, different URLs.


Aside:

RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]

This redirect is in the wrong place. It should be the first rule, not the last.

MrWhite
  • 43,179
  • 8
  • 60
  • 84