You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@httpd.apache.org by Dragon <dr...@crimson-dragon.com> on 2007/03/31 18:56:41 UTC

Re: [users@httpd] Mod RewriteRule Help : Accepting Variable Number Of Arguments

Kristopher Yates did speak thusly:
>Hello,
>
>Here is an example URL I'm trying to create a RewriteRule for:
>
>index.php?section=help&page=test&mode=IN&item=4&action=edit
>
>I have a rule that works when the request URL contains the 
>appropriate number of arguments but does not work when there are 
>fewer arguments than the Rule expects.  I thought by creating 
>multiple (similar) rules would resolve but no luck.  Here is what I 
>have that works as long as I pass all required arguments:
>
>RewriteRule ^(.*)/(.*)/(.*)/(.*)/(.*)$ 
>/index.php?section=$1&page=$2&mode=$3&item=$4&action=$5
>
>The above rule correctly passes 
>http://domain.com/help/test/IN/4/edit to my script as 
>/index.php?section=help&page=test&mode=IN&item=4&action=edit .
>
>I tried creating 5 rules so that, if Apache saw fewer arguments, it 
>would go down to the next rule but that didnt work like I thought it would:
>
>RewriteRule ^(.*)/(.*)/(.*)/(.*)/(.*)$ 
>/index.php?section=$1&page=$2&mode=$3&item=$4&action=$5
>RewriteRule ^(.*)/(.*)/(.*)/(.*)$ 
>/index.php?section=$1&page=$2&mode=$3&item=$4
>RewriteRule ^(.*)/(.*)/(.*)$ /index.php?section=$1&page=$2&mode=$3
>RewriteRule ^(.*)/(.*)$ /index.php?section=$1&page=$2
>RewriteRule ^(.*)$ /index.php?section=$1
>
>How do I write the rule(s) so that, if fewer arguments are passed, 
>it will still work?
>
>Any help would be greatly appreciated.
---------------- End original message. ---------------------

OK, I will take a shot at this... though I am not very experienced 
with mod_rewrite, I do know fair amount about regular expressions.

mod_rewrite documentation is here:
http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html

First off, from the documentation of mod_rewrite, the rules are 
applied in order as defined so they should fall through from one to 
the next if a higher one does not apply. So it seems like your scheme 
should work, why it doesn't is unknown to me. I am not sure about 
this but you might want to try reversing the order of your tests, do 
the smallest number of arguments first.

I think you probably ought to also use the last flag on each rule too 
so it does not skip to the next if it matches. (Now that I think 
about it, this may well be the problem here).

One thing you probably ought to account for is that you are making a 
big assumption in your RE here. That assumption is that there will 
never be a trailing slash on any of the URLs, this may not be a valid 
assumption. To fix that you need to make a change to each RE prior to 
the end of line anchor to indicate either 0 or 1 slashes may exist. 
For example:

         RewriteRule ^(.*)/?$ /index.php?section=$1

This rule would match both of these:
         http://domain.com/help
         http://domain.com/help/

So here is how I suggest you try the rules:

RewriteRule ^(.*)/?$ /index.php?section=$1 [L]
RewriteRule ^(.*)/(.*)/?$ /index.php?section=$1&page=$2 [L]
RewriteRule ^(.*)/(.*)/(.*)/?$ /index.php?section=$1&page=$2&mode=$3 [L]
RewriteRule ^(.*)/(.*)/(.*)/(.*)/?$ 
/index.php?section=$1&page=$2&mode=$3&item=$4 [L]
RewriteRule ^(.*)/(.*)/(.*)/(.*)/(.*)/?$ 
/index.php?section=$1&page=$2&mode=$3&item=$4&action=$5 [L]


Let me know if this helps. I am curious to see if I was on the right track.


Dragon

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Venimus, Saltavimus, Bibimus (et naribus canium capti sumus)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] Mod RewriteRule Help : Accepting Variable Number Of Arguments

Posted by Kristopher Yates <kr...@hotmail.com>.
Hi Eric,

Changing to .+ seems to work fine.  I have only one issue left.  The issue 
is a server error when only one argument is passed.  Here is what I have 
that works when more than one argument is passed:

RewriteRule ^(.+)/(.+)/(.+)/(.+)/(.+)$ 
/index.php?section=$1&page=$2&mode=$3&item=$4&action=$5 [L]
RewriteRule ^(.+)/(.+)/(.+)/(.+)$ 
/index.php?section=$1&page=$2&mode=$3&item=$4 [L]
RewriteRule ^(.+)/(.+)/(.+)$ /index.php?section=$1&page=$2&mode=$3 [L]
RewriteRule ^(.+)/(.+)$ /index.php?section=$1&page=$2 [L]

I thought that, by creating one last rule at the bottom of my list, 
mod_rewrite would catch all instances of when only one argument is passed:

RewriteRule ^(.+)$ /index.php?section=$1 [L]

Adding this final rule breaks everything, resulting in ye olde 'endless 
loop' error for all requests.

I found the following rule as a solution at 
http://forums.searchenginewatch.com/showthread.php?t=3925 but I still get 
the same problem, though the documentation I found said it should work:

RewriteRule ^([^/]+)/?$ /index.php?section=$1 [L]

Any ideas?

Thank you,

Kris

>From: "Eric Covener" <co...@gmail.com>
>Reply-To: users@httpd.apache.org
>To: users@httpd.apache.org
>Subject: Re: [users@httpd] Mod RewriteRule Help : Accepting Variable Number 
>Of Arguments
>Date: Sat, 31 Mar 2007 22:16:09 -0400
>
>On 3/31/07, Kristopher Yates <kr...@hotmail.com> wrote:
>>Hi Dragon,
>>RewriteRule ^(.*)/(.*)/(.*)/(.*)/(.*)/?$
>>/index.php?section=$1&page=$2&mode=$3&item=$4&action=$5 [L]
>>
>>Parsing http://domain.com/section/page/mode/item/action/
>>
>>Results:
>>_REQUEST[section] = "section/page"
>>_REQUEST[page] = "mode"
>>_REQUEST[item] = "action"
>>_REQUEST[action] = empty
>
>All the asterisks are greedy, and the one you expect to be 'action'
>doesn't have anything left to match but the forward slash but the 0
>characters after the slash following "action".  Try making the
>previous expressions non greedy, and maybe use + instead of *
>
>--
>Eric Covener
>covener@gmail.com
>
>---------------------------------------------------------------------
>The official User-To-User support forum of the Apache HTTP Server Project.
>See <URL:http://httpd.apache.org/userslist.html> for more info.
>To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
>   "   from the digest: users-digest-unsubscribe@httpd.apache.org
>For additional commands, e-mail: users-help@httpd.apache.org
>

_________________________________________________________________
Get a FREE Web site, company branded e-mail and more from Microsoft Office 
Live! http://clk.atdmt.com/MRT/go/mcrssaub0050001411mrt/direct/01/


---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] Mod RewriteRule Help : Accepting Variable Number Of Arguments

Posted by Eric Covener <co...@gmail.com>.
On 3/31/07, Eric Covener <co...@gmail.com> wrote:
>  Try making the previous expressions non greedy, and maybe use + instead of *

Sorry, as in /(.+?)/

-- 
Eric Covener
covener@gmail.com

---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] Mod RewriteRule Help : Accepting Variable Number Of Arguments

Posted by Eric Covener <co...@gmail.com>.
On 3/31/07, Kristopher Yates <kr...@hotmail.com> wrote:
> Hi Dragon,
> RewriteRule ^(.*)/(.*)/(.*)/(.*)/(.*)/?$
> /index.php?section=$1&page=$2&mode=$3&item=$4&action=$5 [L]
>
> Parsing http://domain.com/section/page/mode/item/action/
>
> Results:
> _REQUEST[section] = "section/page"
> _REQUEST[page] = "mode"
> _REQUEST[item] = "action"
> _REQUEST[action] = empty

All the asterisks are greedy, and the one you expect to be 'action'
doesn't have anything left to match but the forward slash but the 0
characters after the slash following "action".  Try making the
previous expressions non greedy, and maybe use + instead of *

-- 
Eric Covener
covener@gmail.com

---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org


Re: [users@httpd] Mod RewriteRule Help : Accepting Variable Number Of Arguments

Posted by Kristopher Yates <kr...@hotmail.com>.
Hi Dragon,

Thank you for the reply.  Greatly appreciated.

Your suggestion was helpful in this learning process.  Unfortunately the 
result is the same error I have been getting.

mod_rewrite: maximum number of internal redirects reached. Assuming 
configuration error. Use 'RewriteOptions MaxRedirects' to increase the limit 
if neccessary.

It looks like it should work, but alas, no dice.

What is interesting to note is that if *ONLY* the longest rule exists, and I 
pass it the expected number of arguments, it is incorrectly parsed by 
mod_rewrite:

RewriteRule ^(.*)/(.*)/(.*)/(.*)/(.*)/?$ 
/index.php?section=$1&page=$2&mode=$3&item=$4&action=$5 [L]

Parsing http://domain.com/section/page/mode/item/action/

Results:
_REQUEST[section] = "section/page"
_REQUEST[page] = "mode"
_REQUEST[item] = "action"
_REQUEST[action] = empty

Its as if there is some bug in parsing the first argument where it passes 
the first and second argument to $1.

So then I changed it so I have all five rules modified where the first 
argument is staticly defined and pass it a new URL that I thought would 
match.  This also give unexpected results:

RewriteRule ^superuser/(.*)/?$ /index.php?section=superuser&page=$1 [L]
RewriteRule ^superuser/(.*)/(.*)/?$ 
/index.php?section=superuser&page=$1&mode=$2 [L]
RewriteRule ^superuser/(.*)/(.*)/(.*)/?$ 
/index.php?section=superuser&page=$1&mode=$2&item=$3 [L]
RewriteRule ^superuser/(.*)/(.*)/(.*)/(.*)/?$ 
/index.php?section=superuser&page=$1&mode=$2&item=$3&action=$4 [L]

Parsing: http://domain.com/superuser/page/mode/item/action/

It redirects section=superuser&page=page/mode/item/action/

In all cases, the second rule catches all tests.

I reverse the order of the Rewrite Rules in .htaccess, once again it resorts 
to the other strange parsing:

RewriteRule ^superuser/(.*)/(.*)/(.*)/(.*)/?$ 
/index.php?section=superuser&page=$1&mode=$2&item=$3&action=$4 [L]
RewriteRule ^superuser/(.*)/(.*)/(.*)/?$ 
/index.php?section=superuser&page=$1&mode=$2&item=$3 [L]
RewriteRule ^superuser/(.*)/(.*)/?$ 
/index.php?section=superuser&page=$1&mode=$2 [L]
RewriteRule ^superuser/(.*)/?$ /index.php?section=superuser&page=$1 [L]

Parsing http://domain.com/superuser/page/mode/item/action/

results in redirecting to 
section=superuser&page=page/mode&mode=item&item=action&action=empty
where it mis-parses the first argument and passes what I consider $1 and $2 
together as $1, leaving the last item blank.

Seems like a bug to me but don't quote me on that.  I have been around and 
not a 'noob' but then again I am no mod_rewrite/Apache module guru.  I 
wonder if the last /? in the rule is causing that.

THE GOOD NEWS

I get closest to working with the following rules in this order.

RewriteRule ^superuser/(.*)/(.*)/(.*)/(.*)/?$ 
/index.php?section=superuser&page=$1&mode=$2&item=$3&action=$4 [L]
RewriteRule ^superuser/(.*)/(.*)/(.*)/?$ 
/index.php?section=superuser&page=$1&mode=$2&item=$3 [L]
RewriteRule ^superuser/(.*)/(.*)/?$ 
/index.php?section=superuser&page=$1&mode=$2 [L]
RewriteRule ^superuser/(.*)/?$ /index.php?section=superuser&page=$1 [L]

Though http://domain.com/superuser/page/mode/item/action/ gets misdirected, 
If I take off the trailing slash, the rule works as expected.  Also, the 
shorter rules work when I start deleting things from the end of the URL 
request regardless of the trailing /.  To surmise:

http://domain.com/superuser/page/mode/item/action/ gets misdirected
http://domain.com/superuser/page/mode/item/action works
http://domain.com/superuser/page/mode/item/ works
http://domain.com/superuser/page/mode/item works
http://domain.com/superuser/page/mode/ works
http://domain.com/superuser/page/mode works
http://domain.com/superuser/page/ works
http://domain.com/superuser/page works


For the record, My Apache is Apache/1.3.37 (Unix) mod_fastcgi/2.4.2 
mod_perl/1.29 PHP/5.2.1

My initial config when I set Apache was a no-frills DSO:
./configure --prefix=/usr/local/apache --enable-module=so

Final note, it seems taking /? out of the rules seems to make no difference, 
as rules function the same when it is removed.

Any ideas?

Thanks for your time,

Kris

>From: Dragon <dr...@crimson-dragon.com>
>Reply-To: users@httpd.apache.org
>To: users@httpd.apache.org
>Subject: Re: [users@httpd] Mod RewriteRule Help : Accepting Variable  
>Number Of Arguments
>Date: Sat, 31 Mar 2007 09:56:41 -0700
>
>Kristopher Yates did speak thusly:
>>Hello,
>>
>>Here is an example URL I'm trying to create a RewriteRule for:
>>
>>index.php?section=help&page=test&mode=IN&item=4&action=edit
>>
>>I have a rule that works when the request URL contains the appropriate 
>>number of arguments but does not work when there are fewer arguments than 
>>the Rule expects.  I thought by creating multiple (similar) rules would 
>>resolve but no luck.  Here is what I have that works as long as I pass all 
>>required arguments:
>>
>>RewriteRule ^(.*)/(.*)/(.*)/(.*)/(.*)$ 
>>/index.php?section=$1&page=$2&mode=$3&item=$4&action=$5
>>
>>The above rule correctly passes http://domain.com/help/test/IN/4/edit to 
>>my script as /index.php?section=help&page=test&mode=IN&item=4&action=edit 
>>.
>>
>>I tried creating 5 rules so that, if Apache saw fewer arguments, it would 
>>go down to the next rule but that didnt work like I thought it would:
>>
>>RewriteRule ^(.*)/(.*)/(.*)/(.*)/(.*)$ 
>>/index.php?section=$1&page=$2&mode=$3&item=$4&action=$5
>>RewriteRule ^(.*)/(.*)/(.*)/(.*)$ 
>>/index.php?section=$1&page=$2&mode=$3&item=$4
>>RewriteRule ^(.*)/(.*)/(.*)$ /index.php?section=$1&page=$2&mode=$3
>>RewriteRule ^(.*)/(.*)$ /index.php?section=$1&page=$2
>>RewriteRule ^(.*)$ /index.php?section=$1
>>
>>How do I write the rule(s) so that, if fewer arguments are passed, it will 
>>still work?
>>
>>Any help would be greatly appreciated.
>---------------- End original message. ---------------------
>
>OK, I will take a shot at this... though I am not very experienced with 
>mod_rewrite, I do know fair amount about regular expressions.
>
>mod_rewrite documentation is here:
>http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
>
>First off, from the documentation of mod_rewrite, the rules are applied in 
>order as defined so they should fall through from one to the next if a 
>higher one does not apply. So it seems like your scheme should work, why it 
>doesn't is unknown to me. I am not sure about this but you might want to 
>try reversing the order of your tests, do the smallest number of arguments 
>first.
>
>I think you probably ought to also use the last flag on each rule too so it 
>does not skip to the next if it matches. (Now that I think about it, this 
>may well be the problem here).
>
>One thing you probably ought to account for is that you are making a big 
>assumption in your RE here. That assumption is that there will never be a 
>trailing slash on any of the URLs, this may not be a valid assumption. To 
>fix that you need to make a change to each RE prior to the end of line 
>anchor to indicate either 0 or 1 slashes may exist. For example:
>
>         RewriteRule ^(.*)/?$ /index.php?section=$1
>
>This rule would match both of these:
>         http://domain.com/help
>         http://domain.com/help/
>
>So here is how I suggest you try the rules:
>
>RewriteRule ^(.*)/?$ /index.php?section=$1 [L]
>RewriteRule ^(.*)/(.*)/?$ /index.php?section=$1&page=$2 [L]
>RewriteRule ^(.*)/(.*)/(.*)/?$ /index.php?section=$1&page=$2&mode=$3 [L]
>RewriteRule ^(.*)/(.*)/(.*)/(.*)/?$ 
>/index.php?section=$1&page=$2&mode=$3&item=$4 [L]
>RewriteRule ^(.*)/(.*)/(.*)/(.*)/(.*)/?$ 
>/index.php?section=$1&page=$2&mode=$3&item=$4&action=$5 [L]
>
>
>Let me know if this helps. I am curious to see if I was on the right track.
>
>
>Dragon
>
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>  Venimus, Saltavimus, Bibimus (et naribus canium capti sumus)
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>
>---------------------------------------------------------------------
>The official User-To-User support forum of the Apache HTTP Server Project.
>See <URL:http://httpd.apache.org/userslist.html> for more info.
>To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
>   "   from the digest: users-digest-unsubscribe@httpd.apache.org
>For additional commands, e-mail: users-help@httpd.apache.org
>

_________________________________________________________________
Watch free concerts with Pink, Rod Stewart, Oasis and more. Visit MSN 
Presents today. 
http://music.msn.com/presents?icid=ncmsnpresentstagline&ocid=T002MSN03A07001


---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
   "   from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org