Forum Moderators: phranque

Message Too Old, No Replies

a mod rewrite question

using RewriteMap

         

juanyjuans

10:30 pm on Oct 5, 2009 (gmt 0)

10+ Year Member



Hi,

I'll do my best to explain this simply.

I want to have a URL that appears like:
[mydomain.com...]
that rewrites to:
[mydomain.com...]

So I looked at using a RewriteMap and I got this:
RewriteMap car_map txt:/mysite/car_map.txt
RewriteRule ^find/([a-zA-Z.]*)/$ /find.php?car_id=${car_map:$1} [L]

That works! BUT! this means that within the URL "honda" could be replaced by any string (for examples "http://www.mydomain.com/find/apples/") and the server would still run the file find.php

Is there anyway to restrict the strings used in the URL to the ones in the RewriteMap car_map?

jdMorgan

10:36 pm on Oct 5, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Use a RewriteCond ahead of your RewriteRule to check the RewriteMap return value for non-empty and create a back-reference to it for use in the rule.

Note that the RewriteCond has access to $1, and the RewriteRule will have access to the matched string from the RewriteCond (likely in %1) as well.

Jim

juanyjuans

10:40 pm on Oct 5, 2009 (gmt 0)

10+ Year Member



Could you give me an example of the RewriteCond to illustrate your point?

Something like:
RewriteCond ^find/([a-zA-Z.]*)/$ ${carmap:$1}
RewriteRule ^find/([a-zA-Z.]*)/$ /find.php?car_id=${car_map:$1} [L]

* The syntax above syntax is wrong

Thanks

jdMorgan

11:19 pm on Oct 5, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, you might want to look at the Apache mod_rewrite documentation for stuff like this, instead of trying to guess at the syntax...

RewriteCond ${carmap:$1} ^([0-9]+)$
RewriteRule ^find/([a-zA-Z.]+)/$ /find.php?car_id=%1 [L]

Jim

juanyjuans

10:20 am on Oct 6, 2009 (gmt 0)

10+ Year Member



Can multiple back references (%1 %2 %3 etc.) be used like below?

RewriteCond ${carmap:$1} ^([0-9]+)$
RewriteCond ${location_ids:$2} ^([0-9]+)$
RewriteRule ^find/([a-zA-Z]+)/([a-zA-Z]+)/$ /find.php?car_id=%1&location_id=%2

I tested this and I could only return the back reference from the 2nd RewriteCond through %1

This code would allow me to have:
[mydomain.com...]

jdMorgan

1:28 pm on Oct 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



As documented, you can back-reference only the last-matched RewriteCond. (Before thinking this is bad, be aware that this behavior is critically-important to allowing many of the functions that can be done with RewriteConds.)

However, there's nothing to stop you concatenating the map lookups:


RewriteCond ${carmap:$1}>${location_ids:$2} ^([0-9]+)>([0-9]+)$
RewriteRule ^find/([a-zA-Z]+)/([a-zA-Z]+)/$ /find.php?car_id=%1&location_id=%2

Note that the ">" character is simply an arbitrary non-numeric delimiter character between the two 'fields' -- It has no function as a regular-expressions token, but simply stops the first sub-pattern from matching all but the final digit of the 'combined' variables, as it otherwise would.

Jim

juanyjuans

2:28 pm on Oct 6, 2009 (gmt 0)

10+ Year Member



Wow the solutions can be quite cryptic indeed. I can't say that I like the way the Apache documentation is written.

I have tried the above and it works perfectly so I appreciate your time.

One last question I have is; when a ReWriteMap LookupKey is found can the return value be "" or NULL?

My example would be for a map that stores locations. E.g.
alaska 1
texas 5
usa
nevada 13

In this case the LookupKey "usa" should return "" or NULL.

This would be helpfull when validating the strings in the URL that do not have a particular value.

For example:
[mydoamin.com...]
would be rewritten to:
[mydomain.com...]

By allowing location_id return an empty value would mean that the server side script / sql statement would not filter the results by location_id.

example:

if(!empty($_GET['location_id'])){
SELECT * FROM cars WHERE location_id = $_GET['location_id']
}

jdMorgan

2:38 pm on Oct 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If the return value is null, then the rule as currently rewritten will not be invoked. This was a choice made in an early post in this thread because you said that you did not want the script to run if a return value for a key could not be found. So, you'll have to decide between those two opposite requirements.

To accept a blank location id, simply change the quantifier on the RewriteCond's second subpattern from "+" to "*".

Jim

juanyjuans

2:52 pm on Oct 6, 2009 (gmt 0)

10+ Year Member



> you did not want the script to run if a return value for a key could not be found.

No, it was that I don't want the script to run if the key cannot be found. Regardless if the return value is present.

This way I can control what keys are allowed within the URL string.

If the return value for a key could be "" then it would work.

jdMorgan

5:06 pm on Oct 6, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, the problem is that the only way for RewriteMap to 'signal' that a key can't be found is to return a blank value, and you also seem to want to return a blank value for keys that *are* found, but that you wish to have a blank return value. You can't have it both ways unless you want a third map that contains the same set of keys, but returns a 'valid/not-valid' status for the entries in the now-existing table.

Another way to do it might be to mark each entry in the existing table. For example, put a 'v' in from of each valid lookup value, and test for that in the rule. If the looked-up value would otherwise be blank, then put an 'x' in it. You could then use a sequence of three rules to take action on this information; The first to query the RewriteMap lookup tables and put the results into local variable (See RewriteRule E=Var:Val flag, and use with "-" substitution URL), and the second and third rules to act on the 'x' and 'v' return values. If neither 'x' nor 'v' is found, then don't run either of the second two rules.

A third alternative would be to leave the numeric-only value for valid entries, but put the text-word "blank" or "none" for the return value, and then test for that as above -- there are several ways you could do it.

You'll likely be happier, however, by keeping the mod_rewrite stuff as simple as possible, and doing the heavy lifting in your script(s). Mod_rewrite is extremely powerful for its size, but is not a general-purpose scripting language.

Jim

juanyjuans

5:21 pm on Oct 6, 2009 (gmt 0)

10+ Year Member



Bingo! I love u man.

I prefixed all the values with "v" and it worked. So my map looks like:
chicago v9
usa v
texas v88

Now I have the condition as follows:
RewriteCond ${location_ids:$1}>${car_types:$2} ^v([0-9]*)>([0-9]+)$

thanking you... do you do contract work by any chance?