views:

408

answers:

2

I've got a RewriteMap that looks like this:

Guide           1
Mini-Guide      2
White Paper     3

and I'm including it into Apache via

RewriteMap legacy txt:/var/www/site/var/rewrite_map.txt

I want to create a RewriteRule that will allow only values from the left side of said RewriteMap to be in this position;

RewriteRule ^/section/downloads/(${legacy})/(.*)$ /blah.php?subsection=${legacy:%1}&title=$2

I know I can use ${legacy} on the right side, but can I use it on the left, and if so, how?

+4  A: 

In your map file, the left side is the key and the right side is the value. When you create a rule for matching against a map, you input the key and it outputs the value.

Change your RewriteRule to this:

# Put these on one line
RewriteRule ^/section/downloads/([a-zA-Z-]+)/(.*)$
            /blah.php?subsection=${legacy:$1}&title=$2

The first grouping captures the string in the incoming URL. The $1 in the replacement applies it to the named map. To make a default value, change ${legacy:$1} to ${legacy:$1|Unknown}.

Finally, if you only want the rule to work on values that are in the map file, add a RewriteCond:

RewriteCond ${legacy:$1|Unknown} !Unknown
# Put these on one line
RewriteRule ^/section/downloads/([a-zA-Z-]+)/(.*)$
            /blah.php?subsection=${legacy:$1}&title=$2

The condition says if the map does not return the default value (Unknown), then run the next rule. Otherwise, skip the rule and move on.

Apache RewriteMap

sirlancelot
But I don't want to match on just any string. I only want the ones from the `RewriteMap`. Plus, some of them could have a `/` in their values, so I need it to be specific.
gms8994
@gms8994: You should validate the actual input within your PHP script and not the rewrite map.
Gumbo
A: 

You said, you want to only allow values found in the map. This isn't possible unless you specify an additional restriction in regex for the capture group. There's no way to do it with the map itself. There's no "map.keys" syntax, as far as I know, that you can apply in the left hand side, the pattern.

BUT,
You can specify a default value if the captured value is not found. This way:

## all on one line
RewriteRule ^/section/downloads/([a-zA-Z-]+)/(.*)$
        /blah.php?subsection=${legacy:$1|defaultValue}&title=$2

Replace "defaultValue" with whatever you like. For example 0 (zero), or "notfound", if the given arg is not found in the map.

You can then either rewrite the result of that, with another rule, or just allow it to flow through and provide a "404" message at the URL with the default value.

If you choose to use another rule, then it would look like this:

## all on one line
RewriteRule ^/section/downloads/([a-zA-Z-]+)/(.*)$
        /blah.php?subsection=${legacy:$1|notFoundMarker}&title=$2

## This rule fires if the lookupKey was not found in the map in the prior rule.
RewriteRule ^/blah.php?subsection=notFoundMarker  /404.php   [L]
Cheeso