0

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>
  • 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 03 '14 at 00: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 03 '14 at 00: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 03 '14 at 00: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 03 '14 at 01: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 03 '14 at 01:05
  • @Everydaypanos What do you mean by "breaks completely"? – Shane Madden Jul 03 '14 at 01:06
  • @Belmin Here it is [link](https://docs.google.com/document/d/1Qa_ZZ4MaqmEuujSm3yfMJInUip6R_TOXfRDuo62Tfeg/edit?usp=sharing) – Everydaypanos Jul 03 '14 at 01:07
  • @ShaneMadden I mean it reveals the SCRIPT_FILENAME variable which is a major security risk I think. – Everydaypanos Jul 03 '14 at 01:08
  • @Everydaypanos And how does it reveal it..? What kind of error page or response or log messages are you getting? You need to provide more information if we're going to be able to help. – Shane Madden Jul 03 '14 at 01:09
  • @ShaneMadden When I type in the browser the URI `http://example.com/de` I see a generic Apache Not Found page and the URI on the address bar is now `http://example.com/en/var/www/vhosts/example.com/httpdocs/de/`. Note: This experiment is w/ all `ErrorDocument` removed. I think the bug is in the regex... – Everydaypanos Jul 03 '14 at 01:12
  • Yeah.. something odd going on there. Try turning up the `RewriteLogLevel 9` and setting a location for `RewriteLog`? – Shane Madden Jul 03 '14 at 01:15
  • LogLevel cranked up to 9 [link](https://docs.google.com/document/d/17-coFHU9rVw79mKjLJghOiQtqwLJWXgmVrJQMSwS_U8/edit?usp=sharing) – Everydaypanos Jul 03 '14 at 01:18
  • @ShaneMadden thanks for the help I will focus on combining PHP + Apache for enforcing the structure I need. Apache seems more of a dark art to me :) – Everydaypanos Jul 03 '14 at 01:33

1 Answers1

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?

Belmin Fernandez
  • 10,799
  • 27
  • 84
  • 148
  • 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 03 '14 at 00: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 03 '14 at 00:52
  • Here is a spit from the rewrite.log (level 3 logging) [link](https://docs.google.com/document/d/1GvHzPxBOItpHwYvs4SbE_hmwnL6UIAV5o2BlOmnTqy4/edit?usp=sharing) – Everydaypanos Jul 03 '14 at 00:59
  • Ah, I missed the negation. – Belmin Fernandez Jul 03 '14 at 01:04
  • :) regex devil! – Everydaypanos Jul 03 '14 at 01:13
  • Updated now. Sorry for overlooking that before. – Belmin Fernandez Jul 03 '14 at 01:18
  • ✖ DOESN'T WORK I tried replacing the `RewriteCond` + `RewriteRule` w/ just your `RewriteRule` and it's exactly the same. Although I have a feeling your approach is NOT safe because there are `RewriteCond`s above that might mess w/ the logic. – Everydaypanos Jul 03 '14 at 01:24
  • My Apache knowledge has hit the ceiling. I don't know where these directives are... I just have a simple ServerName example.com | ServerAlias www.example.com | DirectoryIndex index.php | DocumentRoot /var/www/vhosts/example.com/httpdocs ... – Everydaypanos Jul 03 '14 at 01:25
  • thanks for the help I will focus on combining PHP + Apache for enforcing the structure I need. Apache seems more of a dark art to me :) – Everydaypanos Jul 03 '14 at 01:33
  • BTW Accesing directly `example.com/de/` works perfect – Everydaypanos Jul 03 '14 at 01:34