9

my web application structure is:

/var/www/myapp/
    - www/
        - index.php
        - css.php
        - .htaccess

the virtual host is configured as:

<VirtualHost *:80>
        ServerName www.example.org
        DocumentRoot /var/www/myapp/www
        DirectoryIndex index.php index.html
        <Directory /var/www/myapp/www>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>
</VirtualHost>

In /var/www/myapp/www/.htaccess there is:

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteBase /
    RewriteRule css css.php [L,NC]
    RewriteRule .* index.php
</IfModule>

Now, if I call www.example.org I'm correctly redirected to index.php, but if I call www.example.org/css I'm still redirected always to index.php.

If I drop the line "RewriteRule .* index.php" and then call www.example.org/css, I'm correctly redirected to css.php.

What's wrong? Thanks all very much

======== EDIT =========

192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] add path info postfix: /var/www/sviluppo/mattia_dev/example/www/DEV_2 -> /var/www/sviluppo/mattia_dev/example/www/DEV_2/css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/DEV_2/css/example1/test.css -> DEV_2/css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '^(DEV|TEST|PROD)\_[0-9]+\/(css|js|image|static)\/(.+)$' to uri 'DEV_2/css/example1/test.css'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] rewrite 'DEV_2/css/example1/test.css' -> 'css/example1/test.css'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] add per-dir prefix: css/example1/test.css -> /var/www/sviluppo/mattia_dev/example/www/css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] trying to replace prefix /var/www/sviluppo/mattia_dev/example/www/ with /
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (5) strip matching prefix: /var/www/sviluppo/mattia_dev/example/www/css/example1/test.css -> css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (4) add subst prefix: css/example1/test.css -> /css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (1) [perdir /var/www/sviluppo/mattia_dev/example/www/] internal redirect with /css/example1/test.css [INTERNAL REDIRECT]
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/css/example1/test.css -> css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '^(DEV|TEST|PROD)\_[0-9]+\/(css|js|image|static)\/(.+)$' to uri 'css/example1/test.css'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/css/example1/test.css -> css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '.*' to uri 'css/example1/test.css'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] rewrite 'css/example1/test.css' -> 'index.php'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] add per-dir prefix: index.php -> /var/www/sviluppo/mattia_dev/example/www/index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] trying to replace prefix /var/www/sviluppo/mattia_dev/example/www/ with /
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (5) strip matching prefix: /var/www/sviluppo/mattia_dev/example/www/index.php -> index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (4) add subst prefix: index.php -> /index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (1) [perdir /var/www/sviluppo/mattia_dev/example/www/] internal redirect with /index.php [INTERNAL REDIRECT]
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/index.php -> index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '^(DEV|TEST|PROD)\_[0-9]+\/(css|js|image|static)\/(.+)$' to uri 'index.php'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/index.php -> index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '.*' to uri 'index.php'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] rewrite 'index.php' -> 'index.php'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] add per-dir prefix: index.php -> /var/www/sviluppo/mattia_dev/example/www/index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (1) [perdir /var/www/sviluppo/mattia_dev/example/www/] initial URL equal rewritten URL: /var/www/sviluppo/mattia_dev/example/www/index.php [IGNORING REWRITE]

Seems that a first redirect occurs but the mod_rewrite doesn't stop causing an internal redirect. Then, the changed url, is passed to mod_rewrite another time and a second redirect occured but now matching the second rule.

I can't understand it because I've placed the [L] flag just to ensure that the mod_rewrite stops.

Thanks another time

hakre
  • 193,403
  • 52
  • 435
  • 836
MaCi
  • 163
  • 2
  • 11
  • This is interesting. The settings look okay, and I tried it on my system and it works. Maybe you might want to turn on logging for rewrites to see what exactly gets rewritten: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewritelog – jCoder Jul 14 '12 at 15:58
  • I've edited the message, you will find a log. Just focus on the INTERNAL REDIRECT :-) – MaCi Jul 14 '12 at 17:18
  • see @ http://stackoverflow.com/questions/10811081/htaccess-stop-internal-redirect – MaCi Jul 14 '12 at 19:23

2 Answers2

43

You are missing an important fact about the L flag:

It is therefore important, if you are using RewriteRule directives in one of these [.htaccess, <Directory>] contexts, that you take explicit steps to avoid rules looping, and not count solely on the [L] flag to terminate execution of a series of rules

From: L|last (Flag); bold by me

That means, only by using the L does not have your desired effect to prevent the interal redirect. The INTERNAL REDIRECT happens here because it must happen, you have specified it with your .htaccess configuration. The L flag is not the right flag to prevent the INTERNAL REDIRECT.

Let's look closer at your question and what actually happens:

I can't understand it because I've placed the [L] flag just to ensure that the mod_rewrite stops.

Is just that you have the wrong undestanding of the L flag. It will only stop for the current rewriting, meaning, the RewriteRule directives beneath it are not going to be processed in the current round (the inner loop).

If the URI changed L will re-inject into the the next round (the outer loop) as the following technical details flowchart shows:

http://httpd.apache.org/docs/current/rewrite/tech.html

To highlight where the L flag kicks in and where the INTERNAL REDIRECT happens, this is the same graphic with some annotations for your specfic (first) URI rewrite:

enter image description here

It shows that the L flag only exits the inner loop but if the URI has been rewritten (changed) - as in your case - the outer loop takes care that the changed URI will be passed again to all your rewrite rules.

Instead you might want to formulate a condition as the following example from that part of the manual shows:

RewriteBase /
RewriteCond %{REQUEST_URI} !=/index.php
RewriteRule ^(.*) /index.php?req=$1 [L,PT]

(PT has it's own manual entry, is is more or less not part of the solution, just noting because I quoted the example as-is)

What you actually want to use is the END flag:

RewriteRule css css.php [END,NC]

However contact your system administrator if you have the needed apache version for it (Available in 2.3.9 and later). If not, you need to operate with RewriteCond.

hakre
  • 193,403
  • 52
  • 435
  • 836
3

hakre's answer illustrates well what is happening. Besides using the END flag you have a few more options:

  • Use %{ENV:REDIRECT_STATUS} to prevent any further rewrites. This will change after an internal redirect. See this page for more information what is actually happening:

    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule css css.php [L,NC]
    
  • Use %{THE_REQUEST} to match against the request that was made to the server. Since this does not change when you internally redirect, this can be used to prevent further redirects

    RewriteCond %{THE_REQUEST} ^(GET|POST)\ /css\ HTTP
    RewriteRule ^ css.php [L,NC]
    
  • Use a dummy variable in the query string. This would allow to prevent redirecting by defining this variable in a link, but we will use it here to prevent multiple passes:

    RewriteCond %{QUERY_STRING} !noredir=1
    RewriteRule css css.php?noredir=1 [L,QSA,NC]
    

Please note that for each of these examples you need to use this construction for each individual rule.

Sumurai8
  • 20,333
  • 11
  • 66
  • 100
  • Another variant - but not that variable applicable - is to rewrite the rewritten URL to itself so that the no-change exit now L resolution is triggered (e.g. Apache 2.2). – hakre Nov 19 '14 at 14:31