1

I have been looking for an answer for a few hours now, so sorry if this was asked a ton of times, I missed it.

I basically want to make a rewrite to ignore the first directory. That first dir in the path will be different so I thought I could use a regex. But my regex is matching all the way to the file name:

RewriteRule ^([a-z]+)?/(.+)$ $2 [L]

this works if I am one level deep:

http://test.domain.com/one/index.php

I get the actual index page of the root. Which is what I want. but if I were to go deeper:

http://test.domain.com/one/two/anotherfile.php

I get a message saying /anotherfile.php was not found, because it is looking in the root for it. So it seems my regex is not stopping after the last [a-z]. I appreciate any help.

This is Apache2 if that matters at all.

lardlad
  • 99
  • 1
  • 3
  • 8
  • Assuming the input is `one/index.php` and `one/two/anotherfile.php`, the regex works as expected - it does return `two/anotherfile.php` for the second string. Is it possible your problem is somewhere else? Can you post some more details? – Kobi Apr 20 '10 at 20:37
  • Thanks, but I don't know what else it could be. Here is what I have: RewriteEngine On RewriteCond %{REQUEST_URI} !^/lib RewriteCond %{REQUEST_URI} !^/images RewriteRule ^([a-z]+)?/(.+)$ $2 [L] this: http://test.domain.com/one/two/index.php returns the exact same page (/index.php) as: http://test.domain.com/one/index.php – lardlad Apr 21 '10 at 01:19
  • Is there something else I should try? It has to be the regex is being greedy. If I change the regex to "RewriteRule ^(one)?/(.+)$ $2 [L]" it works fine. But I was hoping to make this first directory dynamic. – lardlad Apr 21 '10 at 02:14
  • 1
    A regex should not behave like that, but maybe try `RewriteRule ^([a-z]+)/(.+)$ $2 [L]`. The first group is not optional - I don't know Apache RewriteRule, but I assume if it fails it moves on, so this should be OK. – Kobi Apr 21 '10 at 04:13
  • I've tried this on two servers and I get the same behavior. Is anyone able to verify that this *should* work? If so I know the problem is elsewhere. – lardlad Apr 23 '10 at 15:51

2 Answers2

1

The rewrite engine repeats all the rules until the URI is the same before and after an iteration through the rules. Given the rule, RewriteRule ^([a-z]+)?/(.+)$ $2 [L], and the input: http://test.domain.com/one/index.php, this is what's happening:

  1. The leading slash (prefix) is removed from the URI: one/index.php
  2. The rule is applied, URI matches ^([a-z]+)?/(.+)$
  3. URI is rewritten to /index.php
  4. Internal redirect, new URI (/index.php) doesn't match old URI (/one/index.php) and is run back through the rewrite rules
  5. leading slash is removed
  6. The rule is applied, URI does not match ^([a-z]+)?/(.+)$
  7. URI is not rewritten. new URI (/index.php) is same as old URI before being run through the rewrite engine (/index.php), rewriting stops

Resulting URI is /index.php

But with the input: http://test.domain.com/one/two/anotherfile.php

  1. The leading slash (prefix) is removed from the URI: one/two/anotherfile.php
  2. The rule is applied, URI matches ^([a-z]+)?/(.+)$
  3. URI is rewritten to /two/anotherfile.php
  4. Internal redirect, new URI (/two/anotherfile.php) doesn't match old URI (/one/two/anotherfile.php) and is run back through the rewrite rules
  5. leading slash is removed (two/anotherfile.php)
  6. The rule is appled, URI matches ^([a-z]+)?/(.+)$
  7. URI is rewritten to /anotherfile.php
  8. Internal redirect, new URI (/anotherfile.php) doesn't match old URI (/two/anotherfile.php) and is run back through the rewrite rules
  9. leading slash is removed (anotherfile.php)
  10. The rule is applied, URI does not match ^([a-z]+)?/(.+)$
  11. URI is not rewritten. new URI (/anotherfile.php) is same as old URI before being run through the rewrite engine (/anotherfile.php), rewriting stops

Resulting URI is /anotherfile.php

The [L] doesn't stop the resulting URI from being put back through the rewrite engine, it just stops the rewriting process for the current iteration. You need to change the regular expression or add some kind of rewrite condition. One possibility is adding RewriteRule ^[a-z+]/([a-z]+)?/(.+)$ $2 [L] before the one that you have so that 2 deep directories get handled separately.

Jon Lin
  • 142,182
  • 29
  • 220
  • 220
0

Hmmmm...

Throwing some thoughts out there:

  1. I thought there might be recursive RewriteRule-ing... but I'm not sure, since you put the 'last' rule in there. However, this is the only logical thing I think could explain what is happening.

    1. This is different from your Regex not stopping--this would be Apache continuing on long after we've told it to give up.
  2. If Apache isn't stopping, I'm not sure what recourse you have. Perhaps RewriteCond, DPI (DPI discards PATH_INFO ), analyzing THE_REQUEST, or more?

Sorry I couldn't be of more help. I hope you worked around this in the past year.

SoreThumb
  • 530
  • 1
  • 5
  • 17