mod_rewrite .htaccess causing 500 server error if

2020-02-07 05:33发布

问题:

I've just started using mod_rewrite, this is what I use for a quite basic structured website with multiple language support:

RewriteEngine on
ErrorDocument 404 /error404.php

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z]{2})/([^/]+)$ $2.php?lang=$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z]{2})/$ index.php?lang=$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z]{2})$ index.php?lang=$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ $1.php [L]

My idea was that languages are indicated at the beginning of the URl and need to be two characters (a-z or A-Z). After that there will be a string that refers to a php-file which has the same filename as the string, just .php attached. The language will be added as a GET-Variable (?lang=en).

So, an URl could look like this: /en/index and should then be redirected to index.php?lang=en.

If the URl does not start with a language, but directly with the string, then no GET-variable will be attached to the string. E.g. /index should refer to index.php. If there is no string, then index should be used as default.

So far, so good. Works fine. Just if I enter a string (no matter if I use 2 characters for language or not), the site always shows an 500 Internal Server Error, instead of going to error404.php. Also, if I delete this line (404) in .htaccess, it is still the same error.

So, I assume that there is something wrong with the other lines in the .htaccess that cause this error, does anybody have an idea what this could be?

Any help is highly appreciated!

回答1:

Your rules are looping. At a glance, it looks like your last one:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ $1.php [L]

Say I have this URL, http://your.domain.com/blah, and the file blah.php doesn't exist. This is what's happening.

  1. URI = blah, !-f is true, it's not a file
  2. URI = blah, !-d is true, it's not a directory
  3. URI = blah, internal rewrite to blah.php
  4. blah != blah.php, rewrite rules loop
  5. URI = blah.php !-f is true, it's not a file
  6. URI = blah.php !-d is true, it's not a directory
  7. URI = blah.php, internal rewrite to blah.php.php
  8. blah.php != blah.php.php, rewrite rules loop

This goes on until the rewrite engine has had enough and returns a 500 server error.

You can do one of 2 things here:

  1. Add a directive to make all looping stop no matter what, which is an easy to get around this kind of stuff. But it will break rules that require looping. I don't see anything like that in your rules so it's safe (at least for now) to do this. Just add this to the top of your rules:

    RewriteCond %{ENV:REDIRECT_STATUS} 200
    RewriteRule ^ - [L]
    
  2. Do a pre-emptive check to see if the php file actually exists:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteRule ^([^/]+)$ $1.php [L]
    


回答2:

Helmut, try this (the last rule is the reason for the 500 internal error, and this also includes the suggestion of @DaveRandom to merge rule 2 and 3):

RewriteEngine on
ErrorDocument 404 /error404.php

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z]{2})/([^/]+)$ $2.php?lang=$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z]{2})/?$ index.php?lang=$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9]+)$ $1.php [L]