Forum Discussion
Rewrite URL based on selected node for load-balancing
Dears iRules Gurus and community,
Once again I need your help ^^ I'm wondering how to rewrite an URL of HTTP requests (IPP in fact) depending on the node chosen for load-balancing the traffic.
Typically in ASCII ART or RFC style this would give:
|| ----- if node1 selected for load-balancing -----> https://mynode1/xxxxxx ----> node 1 IIS server
https://mypublicurl/xxxxxx ----> || f5 LTM v11 || ----- if node2 selected for load-balancing -----> https://mynode2/xxxxxx ----> node 2 IIS server
|| ----- if node3 selected for load-balancing -----> https://mynode3/xxxxxx ----> node 3 IIS server
|| etc...
Any idea?
Thanks for your very valuable (and appreciated :D) help!
Cheers.
18 Replies
- Am I asking the impossible?
- Kevin_Stewart
Employee
I think the ASCII art is a little confusing. Can you rephrase? Are you talking about changing the URI based on the selected (load balanced) node, or something in the request URI? - Hi Kevin,
Sorry for confusing you... so I rephrase: I'm talking about changing the URI based on the selected (load balanced) node.
Thanks for your help. - Kevin_Stewart
Employee
There's no real concept of a "node number". Pool members are defined by their IP and port. You could do something like this to "translate" the load balanced pool member into a name value based on a data group entry:when HTTP_REQUEST_SEND { set nodenum [class match -value [LB::server addr] equals lb_server_datagroup] log local0. $nodenum }
Where "lb_server_datagroup" is a data group of type string containing the pool member IPs and an associated name. Example:
10.70.0.1 := node1
10.70.0.2 := node2
10.70.0.3 := node3
Once you have this (arbitrary) name, you can change the URI, Host header, anything else. - Thanks Kevin for your help and your tips. I really appreciate.
In fact I don't really need to know the number of the node, I can directly use the IP address.
Basically I want to rewrite the Host header depending on the node selected for load-balancing the traffic.
What do you think of this iRule:when HTTP_REQUEST_SEND { Need to force the host header replacement and HTTP:: commands into the clientside context as the HTTP_REQUEST_SEND event is in the serverside context clientside { switch -glob [LB::server addr] { "1.1.1.1" { HTTP::header replace Host "newHostHeader01" } "1.1.1.2" { HTTP::header replace Host "newHostHeader02" } etc... } } }
Do you think a more proper way to do that?
Thanks in advance for your valuable feedback. - Kevin_Stewart
Employee
That iRule should definitely do the trick. You probably don't need the "-glob" option though. ;) Thanks Kevin ;) I'll let you the result once implemented (I'm not in the lab now) if you're interested.
Hi,
For information here is the current version of the iRule, thanks for your help to support me to get there. However I still need some help to solve the last issue which is rewriting the Location header, only the domain part and not the rest (ie. path and parameters). Note: I don't know why the feature in http profile did not work so I decided to make it within this iRule.when RULE_INIT Log debug messages to /var/log/ltm? 1=yes, 0=no set static::rewrite_debug 1 External hostname for the web application set static::external "newHost.com" } when HTTP_REQUEST_SEND { Need to force the host header replacement and HTTP:: commands into the clientside context as the HTTP_REQUEST_SEND event is in the serverside context clientside { Different action depending on the node selected for load-balancing switch [LB::server addr] { "1.1.1.1" { HTTP::header replace Host "MyHost01" if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP Host header rewritten with MyHost01"} } "1.1.1.2" { HTTP::header replace Host "MyHost02" if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP Host header rewritten with MyHost02"} } } } } when HTTP_RESPONSE { Replace all internal Host headers with $static::external value defined in RULE_INIT section HTTP::header replace Host $static::external if {$static::rewrite_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: HTTP Host header rewritten with -> $static::external"} if { [HTTP::is_redirect] } { HTTP::header replace Location [string map -nocase "MyHost01.domainname.com newHost.com" [HTTP::header value Location]] HTTP::header replace Location [string map -nocase "MyHost02.domainname.com newHost.com" [HTTP::header value Location]] etc... --> Here I'm looking for a regex to replace the Location header in a single line while concatening the rest of Location value (i.e. with the part after https://domain_name/) } }In a nutshell, now it only remains after [HTTP::is_redirect] to replace the domain name into the Location header in a single line thanks to a regex. For me more easy to say than to do 🙂 That's why I'm still here, asking for your valuable help guys (and girls).
Like this, I won't need to have as much lines as there are backend servers. Once done, we'll can consider this iRule as complete.
I hope I've been clear enough 🙂
Thanks again for your help.- Kevin_Stewart
Employee
Maybe something like this:when HTTP_RESPONSE { if { [HTTP::is_redirect] } { set host_new "newHost.com" set uri_old [string tolower [HTTP::header Location]] if { [scan $uri_old {%*[http://|https://]%[^/]} host_old] } { set map_exp "set uri_new \[string map {$host_old $host_new} $uri_old\]" eval $map_exp HTTP::header replace Location $uri_new } } }
Using the scan and string map commands are just a few ways to do all of this. - nitass
Employee
just another example.
root@(ve11a)(cfg-sync Changes Pending)(Active)(/Common)(tmos) list ltm virtual bar
ltm virtual bar {
destination 172.28.20.111:80
ip-protocol tcp
mask 255.255.255.255
pool foo
profiles {
http { }
tcp { }
}
rules {
qux
}
source 0.0.0.0/0
source-address-translation {
type automap
}
vlans-disabled
}
root@(ve11a)(cfg-sync Changes Pending)(Active)(/Common)(tmos) list ltm pool foo
ltm pool foo {
members {
200.200.200.101:80 {
address 200.200.200.101
}
200.200.200.111:80 {
address 200.200.200.111
}
}
}
root@(ve11a)(cfg-sync Changes Pending)(Active)(/Common)(tmos) list ltm rule qux
ltm rule qux {
when HTTP_RESPONSE {
if { [HTTP::is_redirect] } {
HTTP::header replace Location [string map {MyHost01.domainname.com newHost.com MyHost02.domainname.com newHost.com} [HTTP::header Location]]
}
}
}original response
[root@ve11a:Active:Changes Pending] config curl -I http://200.200.200.101/something
HTTP/1.1 302 Found
Date: Sat, 06 Jul 2013 08:04:13 GMT
Server: Apache/2.2.3 (CentOS)
Location: http://MyHost01.domainname.com/somethingelse
Connection: close
Content-Type: text/html; charset=iso-8859-1[root@ve11a:Active:Changes Pending] config curl -I http://200.200.200.111/something
HTTP/1.1 302 Found
Date: Sat, 06 Jul 2013 08:04:11 GMT
Server: Apache/2.2.3 (CentOS)
Location: http://MyHost02.domainname.com/somethingelse
Content-Type: text/html; charset=iso-8859-1response after passing bigip
[root@ve11a:Active:Changes Pending] config curl -I http://172.28.20.111/something
HTTP/1.1 302 Found
Date: Sat, 06 Jul 2013 08:04:26 GMT
Server: Apache/2.2.3 (CentOS)
Location: http://newHost.com/somethingelse
Content-Type: text/html; charset=iso-8859-1
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