2

this is my first question here, I hope to find a solution. I have a problem with page 404 when the missing page is in a sub "virtual" directory, is used to pass a value to php, in DocumentRoot not exist a directory "de" (for example) for this reason I cannot create a 404 page for each directory. If the url is www.example.com/wrongpage.html works fine shows the custom 404 page thanks to ErrorDocument 404 /404page.php in the htaccess.

If the url is www.example.comm/**de**/wrongpage.html it shows "File not found." and it doesn't load my 404 custom page.

I tried adding "ProxyErrorOverride On" to apache.conf no result even in virtualhost no result. The server has no particular configuration, everything is by default. Since I am using php-fpm before I used php so many configurations are inherited.

Here are the htacces and the virtualhost

<IfModule mod_rewrite.c>
 RewriteEngine On
 RewriteCond %{HTTP_USER_AGENT} libwww-perl.*
 RewriteRule .* . [F,L]
 RewriteBase /
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d

 RewriteRule ^([^/]+)/([^/]+).html         $2.php?ln=$1 [L]
 
</IfModule>

ErrorDocument 404 /404page.php

It doesn't work either by putting an absolute URL

ErrorDocument 404 https://www.example.com/404page.php

And part of virtualhost

DocumentRoot /www/example.com/
AccessFileName .htaccess
<Directory /www/example.com/>
  Options FollowSymLinks MultiViews
  AllowOverride All
  Require all granted
</Directory>

Thank you all

1 Answer 1

0
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+).html         $2.php?ln=$1 [L]

When you request /de/wrongpage.html the above rule "unconditionally" rewrites the request to wrongpage.php?ln=de and it's this that is probably triggering the system "File not found" message. (.php requests are perhaps proxied to a CGI backend?)

You could instead first check that the corresponding .php file exists before rewriting.

Also, do you need to check whether the requested .html file exists? You've stated that the language directory is virtual, so could this ever map to a real file? Likewise, the directory check would also seem redundant. (Presumably you don't have directories that contain .html anyway?)

Your regex that matches the 2-character(?) language code would also seem too general - you are matching "anything"? Is /something/foo.html a valid request? The regex should be as specific as necessary. If your language code is always two lowercase letters then match just that. eg. [a-z]{2}.

And you are missing the end-of-string anchor (ie. $ after .html), so this also matches /foo/bar.html<anything> - potentially resulting in duplicate content.

Try the rule like this instead:

# Rewrite to PHP file if it exists
RewriteCond %{DOCUMENT_ROOT}/$2.php -f
RewriteRule ^([a-z]{2})/([^/]+)\.html$ $2.php?ln=$1 [L]

You don't need the RewriteBase directive here and your user-agent block could be tidied (use a hyphen to indicate no substitution). (The <IfModule> wrapper is not required - unless these directives are optional?)

So, your complete .htaccess file should look like this:

ErrorDocument 404 /404page.php

RewriteEngine On

RewriteCond %{HTTP_USER_AGENT} libwww-perl
RewriteRule ^ - [F]

# Rewrite to PHP file if it exists
RewriteCond %{DOCUMENT_ROOT}/$2.php -f
RewriteRule ^([a-z]{2})/([^/]+)\.html$ $2.php?ln=$1 [L]

Options FollowSymLinks MultiViews

Are you sure you want to enable MultiViews?

1
  • thanks for the answer and the explanations it was enough to add RewriteCond %{DOCUMENT_ROOT}/$2.php -f before RewriteRule ^([a-z]{2})/([^/]+)\.html$ $2.php?ln=$1 [L]. I removed MultiViews Commented Apr 26, 2022 at 14:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.