Apache RewriteRule with RewriteMap

4.8k Views Asked by At

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?

3

There are 3 best solutions below

2
On BEST ANSWER

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

0
On

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]
0
On

another variant:

# %1 will be the subpattern number1 afterwards
RewriteCond %{REQUEST_URI} ^/section/downloads/(.*)
# check if there is no mapping for %1
RewriteCond ${legacy:%1} !^$
# if there is rewrite it
RewriteRule ^/(.*) /blah.php?subsection=${legacy:%1}&title=$2 [R]