Forum Moderators: phranque

Message Too Old, No Replies

mod_rewrite backreferencing problems within RewriteRule pattern

         

gregsullivan

8:28 pm on Jun 5, 2005 (gmt 0)

10+ Year Member



I suspect this is one of those things that will be immediately clear to anyone with a bit more experience than me at regular expressions, but the goal is to internally redirect:

/software/games/foo/graphics/foo.gif

to:

/graphics/software/games/600/foo_01.gif

So while this would work:

RewriteRule ^software/games/([a-z0-9]+)/graphics/([a-z0-9]+).gif$ /graphics/software/games/600/$1_01.gif

It would also match things like:

/software/games/foo/graphics/bar.gif
/software/games/foo/graphics/zzz.gif
/software/games/foo/graphics/yyy.gif

And so on.

When I tried to replace the second ([a-z0-9]+) with a back reference within the pattern, it didn't work. (I was trying to use \1 as a back reference, but I could be wrong about this).

I suspect that either I'm mixing up the syntax for back references within the RewriteRule pattern or that I should be using a RewriteCondition (which I've unsuccessfully tried).

Any suggestions?

Thanks!

jd01

8:36 pm on Jun 5, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi Greg,

/software/games/foo/graphics/foo.gif

Not sure I understand exactly... If you are only trying to redirect one file, then just use that file like this:

RewriteRule ^software/games/foo/graphics/foo.gif$ /graphics/software/games/600/foo_01.gif [L]

If you are trying to match more, or do something different, please post some more specifics.

Hope this helps.

Justin

BTW Adding 'no case' and 'last' [NC,L] should make your rules more solid like this:
RewriteRule ^software/games/([a-z0-9]+)/graphics/([a-z0-9]+).gif$ /graphics/software/games/600/$1_01.gif [NC,L]

gregsullivan

8:53 pm on Jun 5, 2005 (gmt 0)

10+ Year Member



I'll be matching more. There can be any number of games as it will be a database-driven site. Let's say we're using four games called foo, bar, yyy, and zzz; so the following:

/software/games/foo/graphics/foo.gif
/software/games/bar/graphics/bar.gif
/software/games/yyy/graphics/yyy.gif
/software/games/zzz/graphics/zzz.gif

should internally redirect to:

/graphics/software/games/600/foo_01.gif
/graphics/software/games/600/bar_01.gif
/graphics/software/games/600/yyy_01.gif
/graphics/software/games/600/zzz_01.gif

I'm definitely going to be adding flags and optimizing things, but I'm still trying to get past the problem of ensuring two groups in a pattern are identical.

Thanks!

jd01

9:17 pm on Jun 5, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Why not just use the first group (directory) as the variable to the corresponding .gif like this:

RewriteRule ^software/games/([a-z]+)/graphics/[a-z]+\.gif$ /graphics/software/games/600/$1_01.gif [L]

Justin

I think I am just going to keep adding, because my first answer sucked... You can do the comparrison with a condition, but I think it would be much more efficient without. This may need a 'little tweeking' but it's close:

RewriteCond %{REQUEST_URI} ^/$1$2\.gif
RewriteRule ^(software/games/([a-z]+)/graphics/)[a-z]+\.gif$ /graphics/software/games/600/$2_01.gif [L]

This breaks down as follows...
(software/games/([a-z]+)/graphics/) = stores the complete string in $1
([a-z]+) = stores the specific directory in $2

RewriteCond %{REQUEST_URI} ^/ = Copmares the requested URI to $1 'software/games/directory/graphics/' $2 'directory' .gif IOW

software/games/foo/graphics/foo.gif will match, but

software/games/foo/graphics/dog.gif will not

You can elimate the \.gif and leave the line open (no $) to be more efficient, if you do not have any other files that will qualify... this is an implicit 'and everything else'

Like this:
RewriteCond %{REQUEST_URI} ^/$1$2

- I think that's it this time. =)

gregsullivan

5:53 pm on Jun 6, 2005 (gmt 0)

10+ Year Member



I've spent the last couple of hours trying to get this to work without success. Commenting out the RewriteCond causes the RewriteRule you suggested to work properly, although still allowing things like /software/games/foo/graphics/dog.gif to work (as expected without the RewriteCond).

And I can't see any reason why this part:

^/$1$2\.gif

wouldn't work in theory, but I'm still too unsure about how to use backreferences in rewrite conditions to know either way.

Any thoughts?

Thanks again!

jdMorgan

3:01 am on Jun 7, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Atomic back-references, such as \1$ are only available on platforms running operating systems that support POSIX 1003.2 regular expressions. One example is FreeBSD, and there are a few others.

The right side of a RewriteCond must be a string. You cannot compare two variables with RewriteCond. In the absense of POSIX 1003.2, you can't comapre two variables at all in mod_rewrite, so another method must be used.

If you do have access to atomic back-references, compare are possible, but difficult. The trick is to remember that if A+B is equal to A+A, then A and B must be equal. In mod_rewrite terms using atomic back-references, that translates to this equality test:


RewriteCond %1<>%2 ^(.*)<>\1$

Where %1 and %2 in this case back-reference variables defined by an immediately-preceding RewriteCond. The string "<>" is meaningless, and is only used to demarcate the two variables (you could leave it out, or change it to "~" or "<->" or any other "rare" string; it's really just a placeholder). The atomic back reference "\1" makes a copy of the immediately-preceding subpattern, that is "(.*)". So this code compares %1<>%2 to %1<>%1, and if it matches, then %1 and %2 are equal.

A negative compare is then:


RewriteCond %1<>%2 !^(.*)<>\1$

A simpler way to do this is to rewrite your incoming URLs to a unique path that you can test for statically, in order to prevent looping.

Jim