'Custom 404 page not being shown "File not found" shown instead
I've got a website running on Apache 2.4 with PHP 8.0. In my .htaccess file I have this:
RewriteEngine On
RewriteBase /
ErrorDocument 404 /404.php
# Remove .php file extension
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
If I try to access /test.html (a file that doesn't exist), it shows the 404 page, but if I try to access /test it shows "File not found." instead, and in the error log it says "Primary script unknown". Is there any way for it to display the 404 page instead?
Solution 1:[1]
# Remove .php file extension RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^([^\.]+)$ $1.php [NC,L]
Because you are blindly rewriting the request to append .php for any request that does not map to a file (and does not contain a dot). Instead of rewriting the request when the requested file does not exist, you should only rewrite the request when the target file does exist.
When you request /test.html then this does not match ^([^\.]+)$ (which excludes dots), so the directive does nothing and your ErrorDocument is served.
However, when you request /test then this is internally rewritten to /test.php which then seems to be routed directly to your PHP engine (possibly via a proxy), hence the error "Primary script unknown". Unfortunately, this will likely mean that any non-existent .php files will produce the same response - your .htaccess file is not even processed for such requests.
You should test first whether the target .php exists first before trying to rewrite to it.
For example, assuming your .htaccess file is in the document root, try the following instead:
# Remove .php file extension
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]
Now, only when the target .php exists is the request rewritten.
There's no need to backslash-escape literal dots in the regex character class.
Aside: Despite your code comment "Remove .php file extension", this rule does the complete opposite, it appends the .php extension. It allows URLs to work that doesn't include the .php extension.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
