Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
263 views
in Technique[技术] by (71.8m points)

php - mod_rewrite .htaccess causing 500 server error if URl does not exist

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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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]
    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...