Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Hi I have found many resources on mod-rewrite and Apache but I haven't been successful of making a working example.

The example below works for

✓ WORKS example.com/en/page1.phpexample.com/page1.php?ln=en (internal redirect)

✓ WORKS example.com/page1.phpexample.com/en/page1.php (redirect)

✓ WORKS example.com/en/example.com/index.php?ln=en (internal redirect)

✓ WORKS example.com/example.com/en/ (redirect)

✓ WORKS example.com/blahblahexample.com/en/error.php (redirect)

✓ WORKS example.com/en/blahblahexample.com/en/error.php (redirect)

✖ FAILS example.com/deexample.com/en/error.php (redirect - SHOULD BE example.com/de/)

✖ FAILS example.com/de/blahblahexample.com/en/error.php (redirect - SHOULD BE example.com/de/error.php)

    <IfModule mod_rewrite.c>
        RewriteEngine   On
        DirectorySlash  On

        # Force hostname without www REDIRECT
        RewriteCond     %{HTTP_HOST}            !^example\.com [NC]
        RewriteCond     %{HTTP_HOST}            !^$
        RewriteRule     ^(.*)$                  http://%1/$1 [R=301]

        # /xx/somepage.php -> /somepage.php?ln=xx INTERNAL REWRITE
        RewriteCond     %{REQUEST_URI}          ^/../.+ [NC]
        RewriteRule     ^(en|de)/(.*)           $2?ln=$1&%{QUERY_STRING} [L]

        # /en -> /en/ REDIRECT
        RewriteCond     %{REQUEST_URI}          ^/..$ [NC]
        RewriteRule     ^(.*)$                  $1/ [R=302,L]

        # /somepage.php -> /en/somepage.php REDIRECT
        RewriteCond     %{REQUEST_URI}          !^/../ [NC]
        RewriteCond     %{ENV:REDIRECT_STATUS}  !=200
        RewriteRule     ^(.*)$                  /en%{REQUEST_URI} [R=302,L]

        # /en/ -> /en/index.php INTERNAL REWRITE
        RewriteCond     %{REQUEST_URI}          !^/../.+ [NC]
        RewriteCond     %{ENV:REDIRECT_STATUS}  !=200
        RewriteRule     ^(.*)$                  /$1index.php [L]
    </IfModule>

★ NOTE 1: R=302 is for debugging. On server it's actually R=301.

★ NOTE 2: It's on Apache 2.2 so the %{ENV:REDIRECT_STATUS} !=200 bits are trying to emulate the [END] flag of the later Apache 3.2.9.

Thanks!

★ EDIT: Here is more of the .conf file

<Directory /var/www/vhosts/example.com/httpdocs>
    Options +FollowSymLinks -Indexes
    AllowOverride           All

    AddDefaultCharset       utf-8

    ErrorDocument           400             /error.php
    ErrorDocument           401             /error.php
    ErrorDocument           402             /error.php
    ...
    ErrorDocument           500             /error.php

    [above code here]
</Directory>
share|improve this question
    
Where's the redirect to error.php coming from, the application? I think we're missing a step in the redirect process for the failing requests, since Apache isn't configured to send requests to error.php at all. –  Shane Madden Jul 3 at 0:26
    
Hi. Just added the error.php bit. It's standard redirection to a pretty page, I think it has no effect on the problem. Thanks –  Everydaypanos Jul 3 at 0:32
    
Can you disable that part for troubleshooting this? It's hitting some kind of error response, which shouldn't be happening; would be good to see what. Also check the Apache error log for anything relevant? –  Shane Madden Jul 3 at 0:34
    
Can you clear the log and try the two URLs that do not work as expected then post the log snippet in the question? –  Belmin Fernandez Jul 3 at 1:03
    
@ShaneMadden If I remove all ErrorDocument bits it breaks completely and for http://example.com/de it goes to http://example.com/en/var/www/vhosts/example.com/httpdocs/de/ –  Everydaypanos Jul 3 at 1:05

1 Answer 1

You do not have to specify RewriteCond if you could specify the match in RewriteRule. For example:

    # /xx/somepage.php -> /somepage.php?ln=xx INTERNAL REWRITE

    RewriteCond     %{REQUEST_URI}          ^/../.+ [NC]
    RewriteRule     ^(en|de)/(.*)           $2?ln=$1&%{QUERY_STRING} [L]

Should work with just:

    # /xx/somepage.php -> /somepage.php?ln=xx INTERNAL REWRITE
    RewriteRule     ^(en|de)/(.*)           $2?ln=$1&%{QUERY_STRING} [L]

Walking through both URLs that do not work:

example.com/de

  1. Matches rewrite with # /en -> /en/ REDIRECT comment and the URI becomes /de/
  2. Does not match any other rule. Did you expect it to match the last two rules? They won't because of %{ENV:REDIRECT_STATUS} != 200.

Does accessing example.com/de/ directly have different results than the above URL?

example.com/de/blahblah

  1. Matches rewrite with # /xx/somepage.php -> /somepage.php?ln=xx comment and URI becomes blahblah.php?ln=de&othergetvars
  2. Nothing else matches

Can you show us the directives that configure the virtual directories?

share|improve this answer
    
Hi. folders /en/ or /de/ or /xx/ do not actually exist. For example there is only one /page1.php file, only one /error.php file, only one /index.php file. 1. Explicit statements would defeat the purpose above. This rule needs to be general. 2. I think you are wrong here. It matches all cases other than /xx/[something]. By that point in the apache-algorith if a URI is not properly formatted as we want it /xx/... it could only be just a /xx/. So we show the index.php... 3. See initial statement. Directories are virtual. –  Everydaypanos Jul 3 at 0:52
    
... 4. The code's purpose is to just show the de error page. So I guess it would go like: INTERNAL REDIRECT from example.com/de/blahblah -> example.com/error.php?ln=de –  Everydaypanos Jul 3 at 0:52
    
Here is a spit from the rewrite.log (level 3 logging) link –  Everydaypanos Jul 3 at 0:59
    
Ah, I missed the negation. –  Belmin Fernandez Jul 3 at 1:04
    
:) regex devil! –  Everydaypanos Jul 3 at 1:13

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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