Forum Discussion
URL/URI rewrite without changing in Client browser
- Oct 06, 2022
I'd maybe argue that partitions aren't create separate logical BIG-IPs. It's more about building separate administrative domains on a single BIG-IP. Further, partitions can always access the /Common partition. To answer your question though, it depends on the level of isolation, but you should simply be able to point to the VIP in the oter partition,
virtual "/abc-app-dev/np-api-vip" or virtual "/Common/abc-app-dev/np-api-vip"You don't need SNAT to communicate between VIPs on the same BIG-IP.
- Dec 08, 2022
Hi Kevin,
Thanks for your guidance. Here is what I figured out and it is working now. All happened due to your idea so thanks again.
IRule for same routing domain :-
when HTTP_REQUEST {
log local0. "Incoming request: [HTTP::host]:[HTTP::uri]"
if { [set match [class match -value -- "[HTTP::host]:[HTTP::uri]" starts_with datagroup_Name]] ne "" } {
log local0. "Datagroup match: $match"
## Get first URI path in client request
set FIRSTPATH [getfield [HTTP::path] "/" 2]
## Split match into host and path
set matchlist [split $match ":"]
set MATCHHOST [lindex $matchlist 0]
set MATCHPATH [lindex $matchlist 1]
## Replace FIRSTPATH with MATCHPATH (from full HTTP::uri)
set UPDATEDPATH [string map [list "/$FIRSTPATH" "$MATCHPATH"] [HTTP::uri]]
log local0. "Updated host: $MATCHHOST"
log local0. "Updated path: $UPDATEDPATH"
HTTP::host $MATCHHOST
HTTP::uri $UPDATEDPATH
virtual "/path/virtual_server_name"
}
}For different route domain
when HTTP_REQUEST {
log local0. "Incoming request: [HTTP::host]:[HTTP::uri]"
if { [set match [class match -value -- "[HTTP::host]:[HTTP::uri]" starts_with datagroup_name]] ne "" } {
log local0. "Datagroup match: $match"
## Get first URI path in client request
set FIRSTPATH [getfield [HTTP::path] "/" 2]
## Split match into host and path
set matchlist [split $match ":"]
set MATCHHOST [lindex $matchlist 0]
set MATCHPATH [lindex $matchlist 1]
## Replace FIRSTPATH with MATCHPATH (from full HTTP::uri)
set UPDATEDPATH [string map [list "/$FIRSTPATH" "$MATCHPATH"] [HTTP::uri]]
log local0. "Updated host: $MATCHHOST"
log local0. "Updated path: $UPDATEDPATH"
HTTP::host $MATCHHOST
HTTP::uri $UPDATEDPATH
pool pool_name
}
}
Hi Kevin,
I used the first iRule provided by you but seems it is not working. Here is how I used it.
Syntax API URL: https://{host}/{base-or-context-path}/{resource-path}. Here resource path as per customer could be anything so when we are rewriting they only care
about to rewrite https://{host}/{base-or-context-path} and rest of the respurce path can be passed as a string to next VIP. So I used your guidance as following :-
URL at Akana :- https:/api-tint.blah.com/akana-mulesoft-routing-poc/{anything will return 200 OK}
URL at Mulesoft :- https://np.api.us.test.cnb/akana-mulesoft-routing-poc/{anything will return 200 OK}
1. Crate a Data-group Like following :-
ltm data-group internal url_datagroup {
records {
https:/api-tint.blah.com:/akana-mulesoft-routing-poc {
data https://np.api.us.test.cnb:/akana-mulesoft-routing-poc
}
}
type string
}
Note :- here we can add more matching before "type sting" as the list grows.
2. Create an iRule like following and attach it to Akana non-prod VIP (10.10.10.10)
when HTTP_REQUEST {
if { [set match [class match -value -- "[HTTP::host]:[HTTP::uri]" equals url_datagroup]] ne "" } {
log local0. "match = $match"
set matchlist [split $match ":"]
log local0. "match host = [lindex $matchlist 0]"
log local0. "match uri = [lindex $matchlist 1]"
HTTP::host [lindex $matchlist 0]
HTTP::uri [lindex $matchlist 1]
}
}
But when a user is calling the Akana API with the help of the above list it should go to Mulesoft as we are rewriting the https://{host}/{base-or-context-path} but unfortuntaley it is landing on Akana itself not getting directed to Mulesoft. Interseting thing is iRule is taking the hit as we can see in statistics and also there is no error is showing while the iRule is getting the hit.
The [HTTP::host] command is going to return the hostname only (ex. api-tint.blah.com). It looks like you included the protocol scheme in the data group.
It should be:
records {
api-tint.blah.com:/akana-mulesoft-routing-poc {
data np.api.us.test.cnb:/akana-mulesoft-routing-poc
}- NathPrasOct 04, 2022
Cirrus
Hi Kevin_Stewart,
I have applied
ltm data-group internal url_datagroup {
records {
api-tint.blah.com:/akana-mulesoft-routing-poc {
data np.api.us.test.cnb:/akana-mulesoft-routing-poc
}
}With the iRulewhen HTTP_REQUEST {
if { [set match [class match -value -- "[HTTP::host]:[HTTP::uri]" equals url_datagroup]] ne "" } {
log local0. "match = $match"
set matchlist [split $match ":"]
log local0. "match host = [lindex $matchlist 0]"
log local0. "match uri = [lindex $matchlist 1]"
HTTP::host [lindex $matchlist 0]
HTTP::uri [lindex $matchlist 1]
}
}Not sure what went wrong as this time also I can there is hit in iRule but the rewrite is not happeing as the traffic still going to Akana instead of Mulesoft.
Please suggest.
type string
} - Kevin_StewartOct 04, 2022
Employee
Okay, so when you say there's a hit in the iRule, you mean you see the log statements? So the let's say hypothetically that the request URL is: https://api-tint.blah.com/akana-mulesoft-routing-poc.
You should see three log statements:
- match = np.api.us.test.cnb:/akana-mulesoft-routing-poc
- match host = np.api.us.test.cnb
- match uri = /akana-mulesoft-routing-poc
If you see these log entries, then you are indeed also internally changing the HTTP Host header and the URI path. But again, that just means you're changing the Host header and URI on the way to the assigned pool. This isn't doing any traffic routing or redirecting.
- NathPrasOct 05, 2022
Cirrus
Hi Kevin,
Here hit in iRule means when I check the statistics of the iRule I see there is hit count increasing as user test it. About the logs I have not checked it in CLI level in /var/log/ltm but when checked in GUI log section under Local Traffic and searched with the VIP there was no log.
Also as you are saying that host header and URI is getting changed on the way while the traffic is traversing to the exisisting pool, if this is one possibility how to check that or achieve the desired goal. As I stated earlier "api-tint.blah.com" is on a VIP which is in backend holding Akana servers and np.api.us.test.cnb is on another VIP (these two VIPs are in same partition of F5) where in the backend Mulesoft cluster is there.
- NathPrasOct 05, 2022
Cirrus
I have got the following logs from LTM CLI.
[root@abc:Active:In Sync] log # cat ltm | grep Akana_Mulesoft
Oct 4 09:43:52 usva3-bcslba01.abc.com info tmm1[22011]: Rule /abc-app-dev/Akana_Mulesoft <HTTP_REQUEST>: /akana-mulesoft-routing-poc/akana-testing1
Oct 4 09:45:38 usva3-bcslba01.abc.com info tmm3[22011]: Rule /abc-app-dev/Akana_Mulesoft <HTTP_REQUEST>: /akana-mulesoft-routing-poc/akana-testing2I don't see anyother logs
- Kevin_StewartOct 05, 2022
Employee
If you've used the "equals" version of the iRule, then the HOST/URI needs to match exactly, so it should generate a log message when you attempt to access this:
https://np.api.us.test.cnb/akana-mulesoft-routing-poc
But again, because it's an exact match, it won't match this:
https://np.api.us.test.cnb/akana-mulesoft-routing-poc/anything-else
There's a version of the code above that uses a "starts_with" evaluation if the second example is expected. But for coompleteness here it is again with a few minor tweaks:
when HTTP_REQUEST { log local0. "Incoming request: [HTTP::host]:[HTTP::uri]" if { [set match [class match -value -- "[HTTP::host]:[HTTP::uri]" starts_with url_datagroup]] ne "" } { log local0. "Datagroup match: $match" ## Get first URI path in client request set FIRSTPATH [getfield [HTTP::path] "/" 2] ## Split match into host and path set matchlist [split $match ":"] set MATCHHOST [lindex $matchlist 0] set MATCHPATH [lindex $matchlist 1] ## Replace FIRSTPATH with MATCHPATH (from full HTTP::uri) set UPDATEDPATH [string map [list "/$FIRSTPATH" "$MATCHPATH"] [HTTP::uri]] log local0. "Updated host: $MATCHHOST" log local0. "Updated path: $UPDATEDPATH" HTTP::host $MATCHHOST HTTP::uri $UPDATEDPATH } }Put this iRule on the VIP and tail the LTM log while you make a few requests from the client.
tail -f /var/log/ltmAt the very least you should see a single log entry per request showing the "Incoming request: " value. If there's a match against the data group, you'll see the other log entries. If you do not see any other log entries per request, then either the data group does not contain the correct values according to the actual/expected request, or the request isn't as you've described.
- NathPrasOct 06, 2022
Cirrus
Hi Kevin,
Thank you for your kind response.
Now the rewrite is happening from api-tint.blah.com/akana-mulesoft-routing-poc to np.api.us.test.cnb/akana-mulesoft-routing-poc with the help of the iRule but the traffic instead of going to np.api.us.test.cnb/akana-mulesoft-routing-poc (this URL is mapped to VIP in same partition of F5) traffic is hitting to a pool member of URL - api-tint.blah.com/akana-mulesoft-routing-poc.
- NathPrasOct 06, 2022
Cirrus
Can you suggest what more to do after redirect after the URL is rewrite is happening.
- Kevin_StewartOct 06, 2022
Employee
I believe one of your original requirements was that the Host and URL in the browser didn't change. If these applications are sitting on separate client-facing VIPs, that's a rather hard problem to solve. If you want client traffic going to api-tint.blah.com to land on the np.api.us.test.cnb VIP you could do one of two things:
- HTTP redirect the client to the np.api.us.test.cnb VIP. However this WOULD change the Host and URL in the browser.
- Pool to the np.api.us.test.cnb VIP from the api-tint.blah.com VIP, where np.api.us.test.cnb is effectively behind the api-tint.blah.com VIP. If it's separate BIG-IPs, then that should be pretty easy. If it's the same BIG-IP, you can employ VIP targeting in an frontend iRule to forward traffic to the second VIP.
Assuming it's the same BIG-IP, the VIP target could look like this, ammending the previous iRule:
when HTTP_REQUEST { log local0. "Incoming request: [HTTP::host]:[HTTP::uri]" if { [set match [class match -value -- "[HTTP::host]:[HTTP::uri]" starts_with url_datagroup]] ne "" } { log local0. "Datagroup match: $match" ## Get first URI path in client request set FIRSTPATH [getfield [HTTP::path] "/" 2] ## Split match into host and path set matchlist [split $match ":"] set MATCHHOST [lindex $matchlist 0] set MATCHPATH [lindex $matchlist 1] ## Replace FIRSTPATH with MATCHPATH (from full HTTP::uri) set UPDATEDPATH [string map [list "/$FIRSTPATH" "$MATCHPATH"] [HTTP::uri]] log local0. "Updated host: $MATCHHOST" log local0. "Updated path: $UPDATEDPATH" HTTP::host $MATCHHOST HTTP::uri $UPDATEDPATH virtual "/Common/np-api-vip" } } - NathPrasOct 06, 2022
Cirrus
Hi Kevin,
Thanks for the response. It is in the same BIG IP. Both the URLs api-tint.blah.com and np.api.us.test.cnb are different VIPs in the same BIG IP.
- NathPrasOct 06, 2022
Cirrus
Here when you mention /common is it refering to the partion common of BIG IP. Would be "common' in the syntax or the parttion the VIP is sitting.
Example "/abc-app-dev/np-api-vip"
- Kevin_StewartOct 06, 2022
Employee
Correct, it's just the path to the virtual server.
- NathPrasOct 06, 2022
Cirrus
Just to confirm one more thing if these are VIPs are into two separate partition (Two different BIG IPs logically) this same "virtual" command should work as command "virtual" is referring to another VIP here to get land the traffic in the referred VIP.
- NathPrasOct 06, 2022
Cirrus
or it would be something like this
virtual "common/np-api-vip" snat automap
because these two VIPs are in different BIG IPs
- Kevin_StewartOct 06, 2022
Employee
I'd maybe argue that partitions aren't create separate logical BIG-IPs. It's more about building separate administrative domains on a single BIG-IP. Further, partitions can always access the /Common partition. To answer your question though, it depends on the level of isolation, but you should simply be able to point to the VIP in the oter partition,
virtual "/abc-app-dev/np-api-vip" or virtual "/Common/abc-app-dev/np-api-vip"You don't need SNAT to communicate between VIPs on the same BIG-IP.
- NathPrasOct 06, 2022
Cirrus
Hi Kevin,
I used the iRule as following :-
when HTTP_REQUEST {
log local0. "Incoming request: [HTTP::host]:[HTTP::uri]"
if { [set match [class match -value -- "[HTTP::host]:[HTTP::uri]" starts_with url_datagroup]] ne "" } {
log local0. "Datagroup match: $match"
## Get first URI path in client request
set FIRSTPATH [getfield [HTTP::path] "/" 2]
## Split match into host and path
set matchlist [split $match ":"]
set MATCHHOST [lindex $matchlist 0]
set MATCHPATH [lindex $matchlist 1]
## Replace FIRSTPATH with MATCHPATH (from full HTTP::uri)
set UPDATEDPATH [string map [list "/$FIRSTPATH" "$MATCHPATH"] [HTTP::uri]]
log local0. "Updated host: $MATCHHOST"
log local0. "Updated path: $UPDATEDPATH"
HTTP::host $MATCHHOST
HTTP::uri $UPDATEDPATH
virtual "/Common/np-api-vip"
snat automap
}
}While cheking the tcp dump found that VIP of api-tint.blah.com is resetting the connection and error showing as Route domain not match. We tried to with disabling strict isolation on VIP of api-tint.blah.com but result is same(although this time we did not captired the logs)
- Kevin_StewartOct 06, 2022
Employee
Try disabling strict isolation and setting both to use the same (0) parent.
- NathPrasOct 12, 2022
Cirrus
Hi Kevin,
I know it would be a silly question but do I need to add virtual server IP of np.api.us.test.cnb as a pool member to Virtual server api-tint.blah.com or the front end iRule will forward the traffic to target virtual server np.api.us.test.cnb with command "virtual"?
- Kevin_StewartOct 12, 2022
Employee
No. Pooling to another VIP on the same box (in the same route domain) doesn't work.
- NathPrasOct 12, 2022
Cirrus
Hi Kevin,
Both the VIPs are in different route domains.
- Kevin_StewartOct 12, 2022
Employee
Still no. I probably confused the issue adding a note about route domains. Normally to pool to a VIP across route domains, you have to physically leave the box and return. Without doing that, you can't simply pool to another VIP. That's what VIP targeting is for.
- NathPrasDec 08, 2022
Cirrus
Hi Kevin,
Thanks for your guidance. Here is what I figured out and it is working now. All happened due to your idea so thanks again.
IRule for same routing domain :-
when HTTP_REQUEST {
log local0. "Incoming request: [HTTP::host]:[HTTP::uri]"
if { [set match [class match -value -- "[HTTP::host]:[HTTP::uri]" starts_with datagroup_Name]] ne "" } {
log local0. "Datagroup match: $match"
## Get first URI path in client request
set FIRSTPATH [getfield [HTTP::path] "/" 2]
## Split match into host and path
set matchlist [split $match ":"]
set MATCHHOST [lindex $matchlist 0]
set MATCHPATH [lindex $matchlist 1]
## Replace FIRSTPATH with MATCHPATH (from full HTTP::uri)
set UPDATEDPATH [string map [list "/$FIRSTPATH" "$MATCHPATH"] [HTTP::uri]]
log local0. "Updated host: $MATCHHOST"
log local0. "Updated path: $UPDATEDPATH"
HTTP::host $MATCHHOST
HTTP::uri $UPDATEDPATH
virtual "/path/virtual_server_name"
}
}For different route domain
when HTTP_REQUEST {
log local0. "Incoming request: [HTTP::host]:[HTTP::uri]"
if { [set match [class match -value -- "[HTTP::host]:[HTTP::uri]" starts_with datagroup_name]] ne "" } {
log local0. "Datagroup match: $match"
## Get first URI path in client request
set FIRSTPATH [getfield [HTTP::path] "/" 2]
## Split match into host and path
set matchlist [split $match ":"]
set MATCHHOST [lindex $matchlist 0]
set MATCHPATH [lindex $matchlist 1]
## Replace FIRSTPATH with MATCHPATH (from full HTTP::uri)
set UPDATEDPATH [string map [list "/$FIRSTPATH" "$MATCHPATH"] [HTTP::uri]]
log local0. "Updated host: $MATCHHOST"
log local0. "Updated path: $UPDATEDPATH"
HTTP::host $MATCHHOST
HTTP::uri $UPDATEDPATH
pool pool_name
}
}
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