Technical Forum
Ask questions. Discover Answers.
cancel
Showing results for 
Search instead for 
Did you mean: 

URL rewrite through iRule

sunnyman67_1367
Nimbostratus
Nimbostratus

Hi Guys, i have one "Performance (HTTP)" virtual server on F5-1600 series, and i want to change the URL "http://www.abc.com" to "http://partner.abc.com/xyz". i have tried all below scripts :

 

1- when HTTP_REQUEST { if {([string tolower [HTTP::host]] equals "http://www.abc.com")}{ HTTP::header replace Host "http://partner.abc.com/xyz" } }

 

2- when HTTP_REQUEST { if { not ([HTTP::uri] starts_with "/xyz") } { HTTP::uri /xyz[HTTP::uri] } }

 

3- when HTTP_REQUEST { if {[HTTP::uri] equals {http://www.abc.com}} {HTTP::uri {http://partner.abc.com/xyz} } }

 

but i wasn't successful! can anyone help me how can i do this through iRule ?

 

1 ACCEPTED SOLUTION

IheartF5_45022
Nacreous
Nacreous

Hi Sunnyman,

This will work;

if { [IP::addr [IP::client_addr] equals 1.1.1.1] || [IP::addr [IP::client_addr] equals 1.1.1.2} { 
    SNAT with 1.1.1.100
    snatpool VM_SNAT_POOL_1_1_1_100
} elseif { [IP::addr [IP::client_addr] equals 1.1.1.11] || [IP::addr [IP::client_addr] equals 1.1.1.12} { 
    SNAT with 1.1.1.100
    snatpool VM_SNAT_POOL_1_1_1_200
} 

But that's not a very scalable way of doing it if your list is going to grow. If it's going to grow then use an address datagroup, with values snatpool names, which you can use like this

snatpool [class match -value [IP::remote_addr] equals dg_sunnyman_snatpools]

or more correctly;

set snatpool [class match -value [IP::remote_addr] equals dg_sunnyman_snatpools]
if {$snatpool ne "") {
    snatpool $snatpool
 }

View solution in original post

27 REPLIES 27

sunnyman67_1367
Nimbostratus
Nimbostratus

Meanwhile, i want to do that without any redirection, i just want to rewrite the url, thanks all...

 

IheartF5_45022
Nacreous
Nacreous

Hi this is the code you need in HTTP_REQUEST;-

 

if {[string tolower [HTTP::Host]] starts_with "www.abc.com" && [HTTP::path] eq "/"} {
    HTTP::header replace Host "partner.abc.com"
    HTTP::uri "/xyz"
}

In addition, you may need to remove the Performance HTTP profile as it only gives you v limited l7 iRule support.

 

Jo

 

sunnyman67_1367
Nimbostratus
Nimbostratus

Hi Joanna, Thanks a lot, I think your solution is almost the same of my first solution, but it's better to check it with yours. Meanwhile, i have one another problem: if i want to use "HTTP::Host" part of script on "Performance (HTTP)" virtual server mode, F5 tells me to use "HTTP Profile", but when i use "Standard" type of virtual server, F5 can not load balances the web traffic. So i should to use "Performance (HTTP)" mode. In this situation, is there any solution to do that through "Performance (HTTP)" mode? Thanks and Regards Joanna...

 

IheartF5_45022
Nacreous
Nacreous

Hi - Yes you were very close to the correct solution in the first place.

 

You need to change to "Standard" virtual server and apply an HTTP profile (and a oneconnect profile if you are using layer7 persistence, like 'cookie'). If you have any problems then delete and then recreate the virtual server.

 

sunnyman67_1367
Nimbostratus
Nimbostratus

Hi Joanna Thanks a lot for your solution, when i changed the the virtual server type to "Standard" and add "HTTP Profile", it works fine! But now i have another issue: now i want to do URL-rewrite to another port number on another server. For example when clinets want to see "abc.com/ukm", i want to change it to "1.1.1.1:8080/xyz". I've checked it with below script, but i didn't work. Am i wrong?

 if {[string tolower [HTTP::host]] starts_with "abc.com" && [string tolower [HTTP::path]] eq "/ukm"} {

HTTP::header replace Host "1.1.1.1:8080"
HTTP::uri "/xyz"

}

IheartF5_45022
Nacreous
Nacreous

Hi Sunnyman,

No you are not quite right - while it's perfectly valid to include an IP/port number within a Host: header, this does not tell the F5 where to send the traffic. You need to use the node or pool command to inform TMOS where to send traffic. This is the most obvious way using node;-

if {[string tolower [HTTP::host]] starts_with "abc.com" && [string tolower[HTTP::path]] eq "/ukm"} {
    HTTP::header replace Host "partner.abc.com"
    node 1.1.1.1 8080
    HTTP::uri "/xyz"
}

Now having said that, it's not the way I would do it. You should include member 1.1.1.1:8080 in a pool, ie pl_sunnyman_8080 with an appropriate healthcheck and then instruct the F5 to send to the pool;-

if {[string tolower [HTTP::host]] starts_with "abc.com" && [string tolower[HTTP::path]] eq "/ukm"} {
    HTTP::header replace Host "partner.abc.com"
    pool pl_sunnyman_8080
    HTTP::uri "/xyz"
}

The reason this is better is that by having your server in a pool with an appropriate healthcheck, you can have multiple servers in the pool for backup, and also TMOS will already know the state of the servers in the pool, so will only choose one that is UP.

sunnyman67_1367
Nimbostratus
Nimbostratus

Hi Joanna, Thanks again, certainly your solution is fine in related scenarios, but yet there is one small issue: as i mentioned before, i want to change the url to "1.1.1.1:8080/xyz", meanwhile there is no URL on 1.1.1.1. In fact, the new URL that i want to rewrite or to use is "1.1.1.1:8080/xyz". So, i don't want to use "partner.abc.com" in new Host header, i just want to send traffic to new node pool 1.1.1.1:8080 , but at the end of this address the "/xyz" URI should be inserted and makes "1.1.1.1:8080/xyz".Do you have any other idea about this issue?

 

IheartF5_45022
Nacreous
Nacreous

So do you really need to change the Host header at all? It has no effect on where the F5 sends the traffic BTW.

when HTTP_REQUEST {
    if {[string tolower [HTTP::host]] starts_with "abc.com" && [string tolower[HTTP::path]] eq "/ukm"} {
         This pool needs to be created with pool member 1.1.1.1:8080
        pool pl_sunnyman_8080
        HTTP::uri "/xyz"
    }
}
when LB_SELECTED {
     This will update the Host header with the IP:port of the selected server
    HTTP::header replace Host "[LB::server addr]:[LB::server port]"
}

This way when you want to add more servers into your pool, the Host header will get rewritten with whatever server got chosen from the pool, but as I said, unless you have a particular reason to rewrite the Host header I wouldn't bother - it has no effect on routing.

sunnyman67_1367
Nimbostratus
Nimbostratus

Thanks Joanna, i've checked your new solution, but "LB_SELECTED" was not supported. My F5 load-balancer OS version is 10.2.4, but it doesn't support it. Also, i think that the URL i used in L7 is important, because it should be present on destination server, and in my scenario there is no domain name (URL) on the destination server. So, it's important to fill URL with true value. Now, how can i rewrite the URL "http:/abc.com/ukm/" on server 2.2.2.2 , to URL "http://1.1.1.1:8080/xyz/" on server 1.1.1.1 ?

 

IheartF5_45022
Nacreous
Nacreous

Sunnyman - Event LB_SELECTED definitely works on 10.2.4, however if you have problems just do it the way you originally planned ;-

HTTP::header replace Host "1.1.1.1:8080"
HTTP::uri "/xyz"

but you must add in also a "node " or "pool " command also if you want to send traffic to a pool other than the default.

Joanna

sunnyman67_1367
Nimbostratus
Nimbostratus

Joanna, thanks a lot for your regards to my issue, i've checked your new solution yesterday, i think it must be worked properly, i'm testing it in different situations, i should finish my test process as soon as possible, and tell you the results. So let me to do my final check process with our network & vm team. I hope it'll be solved...

 

sunnyman67_1367
Nimbostratus
Nimbostratus

Joanna, thanks a lot for your regards to my issue, i've checked your new solution yesterday, i think it must be worked properly, i'm testing it in different situations, i should finish my test process as soon as possible, and tell you the results. So let me to do my final check process with our network & vm team. I hope it'll be solved...

 

sunnyman67_1367
Nimbostratus
Nimbostratus

Hi Joanna, i checked your last solution, it worked well for some VSs on my load-balancer, but i countered to one another small issue: do you know how can i change only the Context part of a URL? for example, when clinets want to see "www.abc.com/photos?tid5335gfgf53..." , in addition of URL-rewrite, i want to change the context part (fisrt part) of related URI (e.g. to "www.xyz.com/gallery?tid5335gfgf53..."). So, i don't want to change last part of URI (parameters). I want only to change first part of URI (in my example, "photos" to "gallery" with the same parameters as first URI). can you help me again joanna? thanks a lot for your regards...

 

IheartF5_45022
Nacreous
Nacreous

HTTP::uri "/gallery?[HTTP::query]"

 

Sorry to be brief - on phone.

 

sunnyman67_1367
Nimbostratus
Nimbostratus

Thanks a lot joanna for your quick answer, ok , let me try it today or tomorrow and tell you the results...

 

sunnyman67_1367
Nimbostratus
Nimbostratus

Excuse me joanna, are both of below commands same?

1) HTTP::uri "/gallery?[HTTP::query]"

2) HTTP::uri "/gallery?[URI::query [HTTP::uri]]"

IheartF5_45022
Nacreous
Nacreous

Yes you are right!! Was trying to do from memory - should be;

HTTP::uri "/gallery?[URI::query [HTTP::uri]]

sunnyman67_1367
Nimbostratus
Nimbostratus

OK joanna, so let me try it and tell you the final results as soon as possible, Thanks a lot for your regards joanna...

 

sunnyman67_1367
Nimbostratus
Nimbostratus

Hi again joanna, i've checked both commands. For some of URLs they are ok, but for some of them not! Do you have any other idea to maintain query part of a URI and only change the path part of that URI, except these three blow commands ???

HTTP::uri "/ABC/newPics?[URI::query [HTTP::uri]]"
HTTP::uri /ABC/newPics"?[HTTP::query]"
HTTP::uri "/ABC/newPics?[HTTP::query]"

sunnyman67_1367
Nimbostratus
Nimbostratus

Hi joanna, i have one another question: i have one VS, i want to do SNAT through different SNAT Pool List upon the client source IP address. For example, if the source ip address of client is 1.1.1.1/24 or 1.1.1.2/24, VS should changes the source ip address of outgoing packet to 1.1.1.100, and if the source ip address of client is 1.1.1.11/24 or 1.1.1.12/24, VS should changes the source ip address of outgoing packet to 1.1.1.200. I've checked it with below script, but it didn't work! Am i wrong? Can you help me? Is there any need to use of HTTP_REQUEST or some other methods???

when HTTP_REQUEST { 

switch -glob [IP::client_addr] {

  "1.1.1.1" - 
  "1.1.1.2" {
     SNAT with 1.1.1.100
     snatpool VM_SNAT_POOL_1_1_1_100
  }

  "1.1.1.11" - 
  "1.1.1.12" {
    SNAT with 1.1.1.200
    snatpool VM_SNAT_POOL_1_1_1_200
  }

} }

IheartF5_45022
Nacreous
Nacreous

Hi Sunnyman,

This will work;

if { [IP::addr [IP::client_addr] equals 1.1.1.1] || [IP::addr [IP::client_addr] equals 1.1.1.2} { 
    SNAT with 1.1.1.100
    snatpool VM_SNAT_POOL_1_1_1_100
} elseif { [IP::addr [IP::client_addr] equals 1.1.1.11] || [IP::addr [IP::client_addr] equals 1.1.1.12} { 
    SNAT with 1.1.1.100
    snatpool VM_SNAT_POOL_1_1_1_200
} 

But that's not a very scalable way of doing it if your list is going to grow. If it's going to grow then use an address datagroup, with values snatpool names, which you can use like this

snatpool [class match -value [IP::remote_addr] equals dg_sunnyman_snatpools]

or more correctly;

set snatpool [class match -value [IP::remote_addr] equals dg_sunnyman_snatpools]
if {$snatpool ne "") {
    snatpool $snatpool
 }

Wrong reply. Ignore

Please ignore this reply as well.

sunnyman67_1367
Nimbostratus
Nimbostratus

Thanks joanna for your useful help (like ever), but in which event should i use this "if" block? (HTTP_REQUEST? CLIENT_ACCEPTED? , ...). In addition of this question, i want to know what should i set the "SNAT" filed of VS configuration page (Auto-map , None , ...)? Because, i'm going to use of iRule for SNAT operation, in this situation what should i set the corresponding configuration field in related part of VS configuration?

 

IheartF5_45022
Nacreous
Nacreous

It will work in either CLIENT_ACCEPTED or HTTP_REQUEST, however CLIENT_ACCEPTED would be most efficient as you only make the decision once per-TCP connection.

 

I can't give you a definite answer on the other question, but one approach would be to use Automap in the configuration and then to use the snatpool statement. Or just leave it blank in the config and rely on the snatpool in the iRule.

 

sunnyman67_1367
Nimbostratus
Nimbostratus

Thanks a lot joanna, so let me to check all situations and tell you the results...

 

sunnyman67_1367
Nimbostratus
Nimbostratus

Thanks a lot joanna, i've checked your solution and it's OK and works fine! Thanks for your regards and quick replies joanna...