Rewriting Redirects
While best practices for virtualized web applications may indicate that relative self-referencing links and redirects (those which don't include the protocol or the hostname) are preferable to absolute ones (those which do), many applications load balanced by our gear still send absolute self-references. This drives a fairly common requirement when proxying or virtualizing HTTP applications: To manipulate any redirects the servers may set such that they fully support the intended proxy or virtualization scheme. In some cases the requirement is as simple as changing "http://" to "https://" in every redirect the server sends because it is unaware of SSL offloading. Other applications or environments may require modifications to the host, URI, or other headers. LTM provides a couple of different ways to manage server-set redirects appropriately.
HTTP profile option: "Rewrite Redirects"
The LTM http profile contains the "Rewrite Redirects" option which supports rewriting server-set redirects to the https protocol with a hostname matching the one requested by the client. The possible settings for the option are "All", "Matching", Node", and "None".
Rewrite Redirects settings for http profile
Setting | Effect | Resulting Redirect | Use Case |
---|---|---|---|
All | Rewrites all HTTP 301, 302, 303, 305, or 307 redirects | https://<requested_hostname>/<requested_uri> | Use "All" if all redirects are self-referencing and the applicaiton is intended to be secure throughout. You should also use "All" if your application is intended to be secure throughout, even if redirected to another hostname. |
Matching | Rewrites redirects when the request and the redirect are identical except for a trailing slash. See K14775 . | https://<requested_hostname>/<requested_uri>/ | Use "Matching" to rewrite only courtesy redirects intended to append a missing trailing slash to a directory request. |
Node | Rewrites all redirects containing pool member IP addresses instead of FQDN | https://<vs_address>/<requested_uri> | If your servers send redirects that include the server's own IP address instead of a hostname. |
None | No redirects are rewritten | N/A | Default Setting |
Note that all options will rewrite the specified redirects to HTTPS, so there must be an HTTPS virtual enabled on the same address as the HTTP virtual server.
iRule Options
While these options cover a broad range of applications, they may not be granular enough to meet your needs. For example, you might only want to re-write the hostname, not the protocol, to support HTTP-only proxying scenarios. You might need it to temporarily work around product issues such as those noted in SOL8535/CR89873 . In these cases, you can use an iRule that uses the HTTP::is_redirect command to identify server-set redirects and selectively rewrite any part of the Location header using the HTTP::header command with the "replace" option.
Here's an iRule that rewrites just one specific hostname to another, preserving the protocol scheme and URI as set by the server:
when HTTP_RESPONSE { if { [HTTP::is_redirect] }{ HTTP::header replace Location [string map {"A.internal.com" "X.external.com"} [HTTP::header Location]] } }
Here's one that rewrites both relative and absolute redirects to absolute HTTPS redirects, inserting the requested hostname when re-writing the relative redirect to absolute:
when HTTP_REQUEST { # save hostname for use in response set fqdn_name [HTTP::host] } when HTTP_RESPONSE { if { [HTTP::is_redirect] }{ if { [HTTP::header Location] starts_with &quot;/&quot; }{ HTTP::header replace Location &quot;https://$fqdn_name[HTTP::header Location]&quot; } else { HTTP::header replace Location &quot;[string map {&quot;http://&quot; &quot;https://&quot;} [HTTP::header Location]]&quot; } } }
The string map example could quite easily be adjusted or extended to meet just about any redirect rewriting need you might encounter. (The string map command will accept multiple replacement pairs which can come in handy if multiple hostnames or directory strings need to be re-written -- in many cases you can perform the intended replacements with a single string map command.)
Taking it a step further
As I mentioned earlier, redirects are only one place server self-references may be found. If absolute self-referencing links are embedded in the HTTP payload, you may need to build and apply a stream profile to perform the appropriate replacements. An iRule could also be used for more complex payload replacements if necessary. For the ultimate in redirect rewriting and all other things HTTP proxy, I direct your attention to the legendary ProxyPass iRule contributed to the DevCentral codeshare by Kirk Bauer (thanks, Kirk, for a very comprehensive & instructive example!)
- Brian_107072NimbostratusThe HTTP_REQUEST event declaration has an error. The "string map" function is syntactically incorrect. It should be:
- hooleylistCirrostratusNote:
- Brian_107072NimbostratusOkay...the error is not the fault of the poster. My post above was modified by the devcentral filter. To correct the syntax revers the square brackets on both sides of the "HTTP::header Location" string towards the end of the line.
- hooleylistCirrostratusmaybe this will show the issue?
- Brian_107072Nimbostratus:-)
- Should be fixed now guys, thanks for the feedback!
- Jamie_CravensNimbostratusAlso missing a space now:
- Lambert_102051Historic F5 AccountThis line:
- jurgenvdmark_14NimbostratusI've been looking for a method to change absolute redirects into relative redirects. The following does the trick: