Petruza Petruza - 3 months ago 21
Apache Configuration Question

$1 substitution for Apache's RewriteRule doesn't return the first matched expression

I've read everywhere that pattern substitution in Apache's Rewrite Engine works as expected for regular expressions, so I tried:

.htaccess:

RewriteRule (.*) index.php?route=$1


But for a request to
domain.com/some/url
in the get var route I get
index.php
instead of
some/url


In the http var
REDIRECT_QUERY_STRING
I get
route=some/url


But in
QUERY_STRING
I get
route=index.php


What could be wrong here?

PS:
$0
also returns
index.php


If I use
RewriteRule . index.php?route=$1
, I get route=
i
, whatever the request URL.

Answer

$1 is working as expected but problem is your use of this pattern:

(.*)

which matches anything. Your rewrite rule actually loops and runs twice because you don't have any RewriteCond to precent looping.

  1. First it runs for URI=some/url and URI becomes index.php while $1 becomes some/url
  2. Second time it runs for URI=index.php and $1 becomes index.php

You can use this rule to fix this behavior:

# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) index.php?route=$1 [L,QSA]

OR if you want to rewrite existing files and directories to index.php then use:

RewriteRule ^((?!index\.php$).*)$ index.php?route=$1 [L,QSA,NC]

This will rewrite everything except index.php to index.php.