Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
Answers

HTTP rewrite for lots of URLs

Hi all,

I've got a pair of 3400s running 9.0.5. I've created a HTTP-based VS load balancing traffic against a handful of IIS servers.

I'm in a web hosting environment and I've got a situation where I need to do URL rewrites for the each customer on the BigIP.

http://www.A.com/ ---> http://www.IIS_node.com/A
http://www.B.com/ ---> http://www.IIS_node.com/B
.
.
etc (there's a *significant* number of customers... at least 100)

I thought of using the following iRule and I want to see if it made sense.

-------------
when HTTP_REQUEST {
set http_host HTTP::host
switch http_host {
"www.A.com" {HTTP::redirect "http://www.my_vs.com/A/"}
"www.B.com" {HTTP::redirect "http://www.my_vs.com/B/"}
}
}
-------------

Thanks - AJ
0
Rate this Question

Answers to this Question

placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Check out the following thread: Click here http://devcentral.f5.com/Default.aspx?tabid=28&forumid=5&postid=2078&view=topic

-Brian
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
You could do that but your rule would become very large and unmanageable when you start getting to 100s of mappings.

If there is a direct mapping between the domain name and the target uri then you could use regular expressions to extract the domain potion of the host name and dynamically build a uri. Something like this might work:

when HTTP_REQUEST {
# www.A.com -- domain == A.com, company == A
regexp {\.([\w]+)\.com} [HTTP::host] domain company
if { "" ne $company } {
HTTP::redirect "http://www.my_vs.com/$company"
}
}


To make this a bit more robust, you could store all valid companies in a data group and then make sure that the extracted company name is valid before trying a redirect. That way you won't redirect to an invalid site. The downside here is that for each new domain you add, you'll have to update the config on the BIG-IP.


*** BEGIN STRING DATA GROUP ***
class valid_company_names {
"A"
"B"
"C"
}
*** END STRING DATA GROUP ***

*** BEGIN RULE ***
when HTTP_REQUEST {
# www.A.com -- domain == A.com, company == A
regexp {\.([\w]+)\.com} [HTTP::host] domain company
if { "" ne $company } {
if { [matchclass $company equals $::valid_company_names] > 0 } {
HTTP::redirect "http://www.my_vs.com/$company"
}
}
}


Lastly, if you don't have a one-to-one mapping between the middle component of the host and you want to make your rule more readable, try using a string class with the mappings defined in there along with the findclass command.

*** BEGIN STRING DATA GROUP ***
class valid_company_mappings {
"A mapping_for_a"
"B mapping_for_b"
"C mapping_for_c"
}
*** END STRING DATA GROUP ***

*** BEGIN RULE ***
when HTTP_REQUEST {
# www.A.com -- domain == A.com, company == A
regexp {\.([\w]+)\.com} [HTTP::host] domain company
if { "" ne $company } {

# look for the second string in the data group
set mapping [findclass $company $::valid_company_mappings " "]
if { "" ne $mapping } {
HTTP::redirect "http://www.my_vs.com/$mapping"
}
}
}


Hopefully one of these solutions should get you going.

Keep in mind that there are no error conditions in these rules so depending on your situation you might want to throw in some "else's" and reject where appropriate.

BTW, none of these are tested, so throw in some logging and make sure that they are doing what you want before rolling into production

Good Luck!

-Joe
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Thanks Brian and Joe. Great info! I'll give that a try and let you know how it works out.

- AJ
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
This is a follow-on to my previous question...

I did used the following iRules to do the HTTP redirect and it worked.

when HTTP_REQUEST {
set debug "1"
set http_host [HTTP::host]
if {[string equal -nocase $http_host "www.foo.com"]} {HTTP::redirect "http://192.168.1.1/foo[HTTP::uri]"; if $debug {log local0. "redirect --- http://192.168.1.1/foo[HTTP::uri]"}}
}

The problem is that the result is as follows:

http://www.foo.com/ ---> http://192.168.1.1/foo

But I really want the following:

http://www.foo.com/ ---> http://www.foo.com/foo

Any help or pointers would be greatly appreciated.

Cheers, AJ


0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
All you need to do is replace the 192.168.1.1 with the host name. You'll also need to put in a check for the uri to avoid an infinite loop.

Ignoring what we've discussed in the previous posts, you could do the mapping you requested with this code

when HTTP_REQUEST {
if { [string equal -nocase [HTTP::host] "www.foo.com"] and
not ([string tolower [HTTP::uri]] starts_with "/foo") } {
HTTP::redirect "http://[HTTP::host]/foo[HTTP::uri]"
}
}


I added in the "not starts with "/foo" to avoid the infinite loop.

http://www.foo.com -> http://www.foo.com/foo
http://www.foo.com/foo -> http://www.foo.com/foo/foo
http://www.foo.com/foo/foo -> http://www.foo.com/foo/foo/foo
...

-Joe
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Thanks a lot Joe! - AJ
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
After reading these posts we started playing around with the idea of moving or redirector to the BigIP. Two problem pop up, one which should not be a big problem in the future for us is there a way to do a nocase on a class. The second if is or business people have put + signs in there url is there a way I can put the + sign in the class? Thanks

Below is the iRule if it will help


when HTTP_REQUEST {
log start
set lookup [HTTP::host][HTTP::uri]
log $lookup
set mapping [findclass $lookup $::redir_class " "]
if { "" ne $mapping } {
redirect to "$mapping"
log "[HTTP::host] to $mapping"
} else {
set mapping [findclass [HTTP::host] $::redir_class " "]
if { "" ne $mapping } {
redirect to "$mapping"
log "[HTTP::host] to $mapping"
} else {
log "no hit [HTTP::host]"
redirect to "http://www.deere.com"
}
}
}

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Well, both of these questions are accounted for with iRules.

1.) As far as using a non-case sensitive search, that's pretty straightforward. To do this you use the "tolower" command on a string before comparing it. This syntax looks like :


if { [string tolower [HTTP::uri] ] contains "some_string" } {
...



2.) A class can be of multiple types. If you're looking to be able to add characters like a plus ("+") to a class, just be sure the class is set to be a string class, and you can add anything you like in the class.

Hope this helps,
-Colin

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
As for the case comparison, why don't you just store all your values in lower case in the redir_class and then convert the host and uri to lowercase before calling findclass?


when HTTP_REQUEST {
log start
set lookup [string tolower [HTTP::host][HTTP::uri]]
log $lookup
set mapping [findclass $lookup $::redir_class " "]
if { "" ne $mapping } {
redirect to "$mapping"
log "[HTTP::host] to $mapping"
} else {
set mapping [findclass [string tolower [HTTP::host]] $::redir_class " "]
if { "" ne $mapping } {
redirect to "$mapping"
log "[HTTP::host] to $mapping"
} else {
log "no hit [HTTP::host]"
redirect to "http://www.deere.com"
}
}
}


As for the "+" character, I just tested it out and didn't find an issue with that character. Have you tried this and had problems, or were you just wondering whether it would work or not.

-Joe
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
This is what I am entering into the class
www.Commercial.JohnDeereCredit.com http://www.deere.com/deerecom/_Financial+Services/John+Deere+Credit/Grounds+Care+Solutions/Commercial/default.htm

WHen I do that and click Update I get to the following error

Bad Characters. Only the following special characters are allowed: period, asterisk, forward slash, dash, colon, underscore, question mark, equals, at sign, comma and ampersand (.*/-:_?=@,&)

The data group is set up as a string
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
What version of the software are you running? I tested your string out on 9.2 and the GUI let me enter it into a string class.

-Joe
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
We are running version 9.1
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
There is also the URI::decode/URI::encode commands that will decode/encode a URI into rfc compliant form. eg: with decode, %2b will become + and with encode + will become %2b.
0