Forum Moderators: phranque

Message Too Old, No Replies

Using the same RewriteMap file for both Redirect and Rewrite

         

jameshopkins

2:47 pm on May 26, 2009 (gmt 0)

10+ Year Member



Hello there,

I'm new to this forum, and also to mod_rewrite, and am needing to pick your brains on this one.

I have the following code which performs a redirect, then rewrite based on a two RewriteMap directives; the only difference between the two mapfiles are that in one file, the key & values have been reversed.

RewriteCond %{THE_REQUEST} ^GET\ /test\.asp\?meta=([a-z-]+)\ HTTP
RewriteRule ^test\.asp$ http://localhost/${level1-1:%1}? [R=301]

RewriteRule ^([a-z-]+)/?$ test.asp?meta=/${level1:$1

In level1 I have 'horses ho', and in level1-1 I have 'ho horses'.

Obviously it's impossible to have the variables preceding the relevant backreferences in either of the RewriteRules, which is why I had to stick to creating two mapfiles in this instance.

I've been looking at internal functions both for RewriteCond and RewriteMap but can't find anything that would be remotely useful for me.

Could someone point out to me where I'm going wrong and how I can consolidate these two mapfiles?

Thanks in advance

James

jdMorgan

3:47 pm on May 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Let's back up a bit... What is the purpose of the rewrite (specifically), and what are some other the entries in the Rewritemap? I'm wondering if you're using this to divide your resources among several subdirectories which are named according to the first two letters of the requested URL-path, in order to reduce the number of files per directory. If this is the case, then no RewriteMap is needed, and the problem goes away.

If not, then I'd like to point out that you could use a rewritemap or a direct internal rewrite to call a script, passing it several parameters including the 'order' and/or "action" (i.e. rewrite or redirect), and let that script look up the 'transform' in either direction from a single text file or even from your main database if you have one, and then do the redirect or rewrite (actually an 'include' of the desired resource) as requested.

Jim

jameshopkins

10:09 pm on May 26, 2009 (gmt 0)

10+ Year Member



> I'm wondering if you're using this to divide your resources > among several subdirectories which are named according to
> the first two letters of the requested URL-path, in order t > reduce the number of files per directory. If this is the >
> case, then no RewriteMap is needed, and the problem goes
> away.

No this certainly isn't the case, Jim.

The purpose of this rewrite is to convert a URL such as 'test.asp?meta=ho' to '/horses'. What I'm getting myself confused on is how I can utilise the same mapfile for both redirect and rewrite RewriteRules, since the position of the pattern and substition values (in my example, at least) aren't consistent:-

*Redirect*: RewriteRule ^test\.asp$ [localhost...] [R=301]

*Rewrite*: RewriteRule ^([a-z-]+)/?$ test.asp?meta=/${level1:$1}

If the pattern and substitution strings were placed in the same order in both RewriteRules, then I'd have no problem using the same mapfile. The underlying issue, however, is that between RewriteRules, I'm declaring both keys and values as variables.

Other entries in the RewriteMaps include

*level1* - 'sheep sh' 'geese ge' 'dogs do' 'pigs pi'
*level1-1* - 'sh sheep' 'ge geese' 'do dogs' 'pi pigs'

It's probably worth mentioning at this stage, that I'm actually not using Apache for this; I'm using the ISAPI Rewrite 3 plugin for IIS 5, so I'm fairly limited as to what scripting I can perform.

g1smd

10:23 pm on May 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



*** convert a URL such as 'test.asp?meta=ho' to '/horses' ***

A rewrite does not do that.

It works the other way. It accepts a URL request for example.com/horses and fetches content from the internal server filepath at /test.asp?meta=ho - the difference between a URL 'used on the web' and a filepath 'used inside the server' is key here.

It works in conjunction with a redirect that accepts URL requests for example.com/test.asp?meta=ho and tells the user to make a new request for the URL example.com/horses instead.

jameshopkins

10:31 pm on May 26, 2009 (gmt 0)

10+ Year Member



Apologies, g1smd. My wording is incorrect in my last post.

I am clear as to how mod_rewrite works in this respect; 'test.asp?meta=ho' exists on the internal server (and also on our live site, which I'm demoing by invoking the proxy passthrough feature) and have successfully redirected (301 from 'test.asp?meta=ho' to '/horses') and rewritten (accepts a request for '/horses' and fetches the content located at 'test.asp?meta=ho'.

jdMorgan

12:11 am on May 27, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



OK, I didn't answer the fundamental question then, which is that you cannot use one map file --regardless of variable order in the rules or whether those rules perform internal rewriting or external redirection-- due to the fact that the 'key' and the 'looked up data' are swapped in each case, but RewriteMap lookup tables are always ordered key first, then lookup data.

That is why I suggest writing a script for use either during the URL-to-filename-translation API phase by calling it as a RewriteMap, or during the content-handler phase by passing (rewriting) all requests to that script.

In the first case, you can pass the script a variable (see RewriteRule's [E] flag) telling it which way you want to translate (long to short, or short to long) in addition to the 'key' received in the client-requested URL. It can use a pre-defined data table to do the requested operation, and return the required looked-up value.

In the second case, you just pass (internally rewrite) *all* requests to a PHP or PERL script, and let it determine whether a redirect is needed. If not, it can either 'include' the requested resource (file), generate the requested content, or invoke another script, as desired.

My main point is that if you have a two-column lookup table with 'long' and 'short' value columns, and you want to call it with key=short and get answer=long, and you also want to call it with key=long and get answer=short, then a 'text' RewriteMap won't work for you. You'll need to write your own script which can use any lookup table you like in any format you like to look up short from long or long from short (assuming there are no unresolvable collisions in short values such as ho=horse and ho=house.)

Jim

jameshopkins

4:17 pm on May 27, 2009 (gmt 0)

10+ Year Member



Thanks for the reply, jdMorgan.

I was actually having a look through the RewriteRule documentation a little earlier and was surprised to see that there was no predefined internal function that would solve this issue.

I've had a word with the devs here, and it's not too much of a problem creating two almost idenitical lookup tables (just reversed key/values) as they would be system generated. Will having two lookup tables for this purpose, as opposed to a central one, have a significant performance effect on lookups? FYI, we will have around 5000 keys/values

Regards

James

jdMorgan

6:11 pm on May 27, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If you use two tables and two RewriteMaps, then neither one affects the performance of the other. Use the "dbm" hash-table format for best performance, not the plain-text format.

You should also look into the script method, and see whether that would allow you to integrate/centrailze this data in your main CMS database (if you use one), which would likely make administration a whole lot easier. You can use RewriteMap to call a simple PERL script to open your database and get the needed data, for example, returning it for use by the RewriteRule.

I advise you to take a step back, look at the big picture, and don't rush to implementation by focusing on one directive in one module for 'the' solution... Don't rush from 'requirements specification' to implementation, in other words.

And do beware of the potential for 'irresolvable collisions' with this plan as I mentioned above, between "ho=horse" and "ho=house."

Jim

jameshopkins

6:14 pm on May 27, 2009 (gmt 0)

10+ Year Member



Some great advice, jdMorgan. Much appreciated