How to rewrite Location response header in a proxy setup with Apache?
Asked Answered
O

1

19

I have a primary proxy which sends requests to a secondary proxy on which OpeenSSO is installed.

If the OpenSSO agent determines that the user is not logged in, it raises a 302 redirect to the authentication server and provides the original (encoded) URL that the user requested as a GET parameter in the redirect location header.

However, the URL in the GET variable is that of the internal (secondary) proxy server, not the original proxy server. Therefore, I would like to edit/rewrite the "Location" response header to give the correct URL.

E.g.

  1. http://a.com/hello/ (Original requested URL)
  2. http://a.com/hello2/ (Secondary proxy with OpenSSO agent)
  3. http://auth.a.com/login/?orig_request=http%3A%2F%2Fa.com%2Fhello2%2F (302 redirect to auth server with requested URL of second proxy server encoded in GET variable)
  4. http://auth.a.com/login/?orig_request=http%3A%2F%2Fa.com%2Fhello%2F (Encoded URL is rewritten to that of the original request)

I have tried pretty much all combinations of headers and rewrites without luck so I'm thinking it may not be possible. The closest I got was this, but the mod_headers edit function does not parse environment variables.

# On the primary proxy.
RewriteEngine On
RewriteRule ^/(.*)$ - [E=orig_request:$1,P]
Header edit Location ^(http://auth\.a\.com/login/\?orig_request=).*$ "$1http%3A%2F%2Fa.com%2F%{orig_request}e"
Oversew answered 30/4, 2013 at 10:4 Comment(0)
B
26

ProxyPassReverse

ProxyPassReverse should do this for you:

This directive lets Apache adjust the URL in the Location, Content-Location and URI headers on HTTP redirect responses.

I'm not sure why your reverse proxy isn't behaving this way already, assuming you're using a pair of ProxyPass and ProxyPassReverse directives to define it.

Editing the Location Header

If you want to be able to edit the Location header as you describe, you can do it as of Apache 2.4.7:

For edit there is both a value argument which is a regular expression, and an additional replacement string. As of version 2.4.7 the replacement string may also contain format specifiers.

The "format specifiers" mentioned in the docs include being able to use environment variables, e.g. %{VAR}e.

You might also want to consider modifying your application such that the orig_request URL parameter is relativized, thus potentially eliminating the need for Header edits with environment variables.

Relative Path Location Header

You can also try using a relative path in your Location header, which would eliminate the need to explicitly map one domain to the other. This is officially valid as of RFC 7231 (June 2014), but was was widely supported even before that. You can relativize your Location header using Apache Header edit directives (even prior to version 2.4.7, since it wouldn't require environment variable substitution). That would look something like this:

Header edit Location "(^http[s]?://)([a-zA-Z0-9\.\-]+)(:\d+)?/" "/"
Black answered 5/3, 2015 at 13:50 Comment(4)
Thanks for the suggestion to simply edit the location header directly!Sayce
ProxyPassReverse doesn't seem to work for 201 Created. Any work-around for that?Welcome
The regex to edit Location header doesn't strip off colon and port. I used this instead with success: Header edit Location "(^http[s]?://)([^/]+)" ""Oldenburg
I found that using ProxyPassReverse in a Location block resulted in the redirect going back to the IP of a load balancer in the proxy chain, rather than the external FQDN. Using Header edit Location worked perfectly, and feels more intuitive anyway. Thanks for your post.Hopeless

© 2022 - 2024 — McMap. All rights reserved.