apachemod-rewriterewritemap

Using variable in RewriteCond condition patern


I want to associate user Ids to a specific application Id like:

<user_id> <app_id>  
615 1
616 7
617 3
618 3    

My URIs looks like:

/<app_id>/<user_id>/...

Now, I want to be able to easily change the application without impacting the user bookmarks. In my example, I want both

/1/615/index.html or /3/615/index.html

to be served as

/1/615/index.html

With the following rule, I get infinite loop:

RewriteMap map dbm:user-application.map
RewriteRule ^/([0-9]+)/([0-9]+)/(.*)$ /${map:$2}/$2/$3 [R,L]              
...
#other proxy code to forward request to applications

I understand that after the redirection, Apache will always execute the same rule. I then tried to add a rewrite condition to block the loop, like

RewriteMap map dbm:user-application.map
RewriteCond %{REQUEST_URI} !^/${map:$2}
RewriteRule ^/([0-9]+)/([0-9]+)/(.*)$ /${map:$2}/$2/$3 [R,L]              

If I read correctly my rewrite logs, I can see that the variable !^/${map:$2} is not replaced in the condition pattern, but checked "as it". And then the condition is always true, and I still get my infinite loop.

Any idea to block the loop as soon as the application id match my map?


Solution

  • /3/615/index.html is correctly redirecting to /1/615/index.html

    The problem is that you are redirecting /1/615/index.html to /1/615/index.html as well - you want to detect the case in which the map transform is a no-op and not redirect at all in that case.

    If you don't care about the user-facing URL, just change the [R,L] to [L] (removing the R) and you should be fine since it won't trigger a new round-trip from the client.

    You're right that the $2 backreference won't work in a RewriteCond expression; this is because the RewriteRule hasn't yet been evaluated. You might be able to use %n - style backreferences to a regex in a previous RewriteCond...

    RewriteCond {%REQUEST_URI} ^/([0-9]+)/
    RewriteCond {%REQUEST_URI} !^/${map:%1}
    

    But I have not tested this, so YMMV.