Forum Discussion
pool-member specific rewrite of http URI
Hi everybody,
I have the following requirement:
There is a pool consisting of two members (same IP, different port). HTTP requests coming in to the according virtual must be rewritten as follows: If the URI starts with "/abc/" and selected pool member is 1, the first part of the URI needs to rewritten to "/def/", if member 2 is selected by the LB, it needs to be rewritten to "/ghi/". Due to the member-specific part of this, a rewrite or stream profile cannot be used without an iRule.
I tried the following iRule, which seemed to work at first (using cURL as testing tool):
when LB_SELECTED {
if { [HTTP::uri] starts_with "/abc/" } {
if { [LB::server port] equals 8001 } {
HTTP::uri [string map {"/abc/" "/def/"} [HTTP::uri] ]
}
elseif { [LB::server port] equals 8002 } {
HTTP::uri [string map {"/abc/" "/ghi/"} [HTTP::uri] ]
}
}
}
However, it turned out that subsequent http requests coming in through the same http 1.1 session with keep-alive are not rewritten, which is totally understandable, because LB_SELECTED is only triggered once.
Hence, after struggling with variable substituition with string maps in curly braces for a while, I moved forward to the following rule:
when LB_SELECTED {
if { [LB::server port] equals 8001 } {
set newuri_prefix "/def/"
}
elseif { [LB::server port] equals 8002 } {
set newuri_prefix "/ghi/"
}
}
when HTTP_REQUEST {
if { [HTTP::uri] starts_with "/abc/" } {
HTTP::uri [string map -nocase [list "/abc/" "$newuri_prefix"] [HTTP::uri] ]
}
}
This does not work either, because HTTP_REQUEST obviously is triggered before LB_SELECTED, meaning that $newuri_prefix is empty. I came to this conclusion because of the following log entries being written when the rule is executed:
err tmm[10833]: 01220001:3: TCL error: ...somerulename... - can't read "newuri_prefix": no such variable while executing "list "/abc/" "$newuri_prefix""
Because of that, I also cannot replace "LB_SELECTED" with "HTTP_REQUEST" in the first rule above, because [LB::server port] is not yet set then.
Now I'm running out of ideas... Any suggestions on how to achieve this? Any hint is appreciated. Many thanks in advance!
1 Reply
Hi Tatmotiv,
you may try to use the HTTP_REQUEST_SEND event. This event will trigger after LB_SELECTED has choosen the member and also on every subsequent HTTP request...
when HTTP_REQUEST_SEND { clientside { if { [HTTP::uri] starts_with "/abc/" } { if { [LB::server port] equals 8001 } { HTTP::uri "/def[string range [HTTP::uri] 4 end]" } elseif { [LB::server port] equals 8002 } { HTTP::uri "/ghi[string range [HTTP::uri] 4 end]" } } } }Note: I've changed your code to use [string range] command in combination with substitution. Its much more stable and also performant to just cut/add the leading portion that needs to become replaced. You may have to change the 4 to the length of the string that needs to become cutted.
Cheers, Kai
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com