Execute RewriteRule proxy redirection directive after all others

I have a backend application behind a reverse proxy protected by an SSO. The SSO exports an HTTP header after successful authentication containing the userid. I need to pass this uid and other data to a program that will sign the all thing.

Here's how it works:

  1. Define the script with RewriteMap
  2. Set an environment var with the SSO-exported header value
  3. Call the script, get the values returned and append them to env var
  4. Check the env var and create a cookie with those values

Then the last RewriteRule directive will pass the traffic to the backend application, the thing is, as soon as I set the RewriteRule with the P flag, all the above variable affectations no longer work.

Question : How can I manage to execute all my directives and thus the cookie creation before proxying all the traffic so my cookie is available in my backend app ?

RewriteMap  cookiemap prg:/dir/cookieSign.py
RewriteRule ^ - [env=LLNGUID:%{HTTP:Test}]

RewriteCond ${cookiemap:%{REMOTE_ADDR}-%{ENV:LLNGUID}} ^(.*)\s(.*)\s(.*)\s([a-z]+)$
RewriteRule ^ - [E=SIGNATURE:%1,E=SETTIME:%2,E=SETIP:%3,E=UIDSCRIPT:%4]

RewriteCond "%{ENV:SIGNATURE}" "!^$"
RewriteCond "%{ENV:SETTIME}" "!^$"
RewriteCond "%{ENV:SETIP}" "!^$"
RewriteCond "%{ENV:UIDSCRIPT}" "!^$"
RewriteRule ^ - [CO=MY_COOKIE:userid=%{ENV:UIDSCRIPT}&sign=%{ENV:SIGNATURE}&time=%{ENV:SETTIME}&ip=%{ENV:SETIP}:.test.ltd:86400:/:true:true]

RewriteRule "^(.*)$" "http://127.0.0.1:8080$1" [P,L]

Thanks :)


The problem is not the order of execution - the directives are being executed in the order shown - but an issue with variable scope and cookie setting.

The environment variables you set here are not going to be available to the target server, since this is a different scope.

The cookie you are "setting" will not be available to your script in the current request. Setting a cookie (eg. with the CO flag) sets a Set-Cookie HTTP response header on the HTTP response back to the client/browser. The cookie is only sent back to your server on the next request when the browser (hopefully) sends back a Cookie HTTP request header.

If you want to send this information to your backend server for the current request then you need to use a different method. Perhaps a query string on the proxied request?

For example:

RewriteMap  cookiemap prg:/dir/cookieSign.py

RewriteRule ^ - [env=LLNGUID:%{HTTP:Test}]

RewriteCond ${cookiemap:%{REMOTE_ADDR}-%{ENV:LLNGUID}} ^([^\s]+)\s([^\s]+)\s([^\s]+)\s([a-z]+)$
RewriteRule ^ - [E=SIGNATURE:%1,E=SETTIME:%2,E=SETIP:%3,E=UIDSCRIPT:%4]

RewriteCond %{ENV:SIGNATURE} .
RewriteCond %{ENV:SETTIME} .
RewriteCond %{ENV:SETIP} .
RewriteCond %{ENV:UIDSCRIPT} .
RewriteRule ^ - [ENV=MY_QUERY:userid=%{ENV:UIDSCRIPT}&sign=%{ENV:SIGNATURE}&time=%{ENV:SETTIME}&ip=%{ENV:SETIP}]

RewriteRule (.*) http://127.0.0.1:8080$1?%{ENV:MY_QUERY} [P]

Notes:

  • Changed the regex that matches the output of the rewritemap to use [^\s]+ instead of .* to avoid unnecessary backtracking.
  • No need to surround all arguments in quotes unless they contain spaces.
  • Instead of checking for not-empty ("!^$"), it's arguably simpler to check that it is something, ie ..
  • The L flag is not required when using the P flag (it is implied).