2

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!

pnuts
  • 58,317
  • 11
  • 87
  • 139
Helmut
  • 1,377
  • 1
  • 15
  • 25
  • 2
    Type `RewriteLog /path/to/your/rewrite.log` and set debug level with `RewriteLogLevel 9`. Please look at error.log (`ErrorLog /path/error.log`) for `500`'s reason. – kbec Sep 17 '12 at 13:06
  • 1
    Could it be the case that you are going into infinite loop. Try adding condition that the file is not a .php file – Ashwini Dhekane Sep 17 '12 at 13:17
  • 1
    The second and third `RewriteRule`s can be merged into one: `RewriteRule ^([a-zA-Z]{2})/?$ index.php?lang=$1 [L]`. This probably wont fix the problem, just a general comment. – DaveRandom Sep 17 '12 at 13:20
  • @AshwiniDhekane: oh, yes.. that is probably the reason! thx... how would you add such a condition?? – Helmut Sep 17 '12 at 14:09
  • @kbec: sorry to ask, but do I have to write this into the .htaccess or where else? Adding it to .htaccess gives me 500 error code immediately in any case and the .log file stays emtpy... – Helmut Sep 17 '12 at 14:17
  • @Helmut: You must add logging directives in server (`httpd.conf`) or vhost configuration, not `.htaccess` – kbec Sep 17 '12 at 14:48

2 Answers2

3

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]
    
Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • that's just genius! thanks so much, Jon Lin! And thanks for your time to explain that much in detail! You really taught me a lot now! – Helmut Sep 17 '12 at 16:49
1

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]
Chris
  • 3,756
  • 7
  • 35
  • 54