Forum Discussion
iRule Array with string map redirects not working
Hi,
I'm trying to create a iRule with arrays that sendt traffic to both pools and 302 redirection.
The iRule should behave like this:
The first array simply forwards traffic to a pool. It's working as intended.
The second array should redirects certain URI's to a different URL. It get's difficult when I also need to append some of the the URI to the redirect target.
Example:
Requests to https://bee.test.example.no/cfs/whatever should redirect to https://cfs-ws-customer.vendor.no/whatever
So I would like to remove "/cfs/" from the URI but append/keep the rest and add it to the redirect URL.
I've tried using string map, but I can's seem to get it to work.
More examples:
Requets to bee.test.example.no/caf/whatever/example should redirect to https://banktest.portal.no/dummy-text_to_show-something-web/whatever/example
Requets to bank.test.example.no/insurance/whatever/dummy should redirect to http://test.dummy.customer.no/example/whatever/dummy.
Requets to redaktor-*.test.example.no/cfs/example/stuff should redirect to https://cfs-ws-customer.vendor.no/example/stuff
I would appreciate any help or tips! Let me know if something is unclear 🙂
`when HTTP_REQUEST {
array set pools {
sliders.test.example.no pool_example_test
bee.test.example.no pool_example_test
tinypower.test.example.no pool_example_test
tbank.test.example.no pool_example_test
bank.test.example.no pool_example_test
womvalley.test.example.no pool_example_test
redakto- pool_example_redaktor
priceapi1-sitecore1.test.example.no pool_example_redaktor
}
array set redirects {
/caf https://banktest.portal.no/dummy-text_to_show-something-web/
/insurance http://test.dummy.customer.no/example/
/cfs https://cfs-ws-customer.vendor.no/
}
foreach {web_uri new_destination} [array get redirects] {
if { [string tolower [HTTP::uri]] starts_with "$web_uri" } {
HTTP::respond 302 noserver Location "$new_destination[string map {$web_uri [HTTP::uri]} [HTTP::uri]]"
return
}
}
foreach {host_header member_pool} [array get pools] {
if { ([string tolower [HTTP::host]] equals $host_header) }{
pool $member_pool
return
}
elseif { ([string tolower [HTTP::host]] starts_with $host_header) }{
pool $member_pool
return
}
}
HTTP::respond 200 Content "This site does not exist"
}`
3 Replies
- cjunior
Nacreous
Hello, I think you are combining curly braces with variables and this avoids their expansion. So, it should be something like this:
HTTP::respond 302 noserver Location "$new_destination[string map "$web_uri [HTTP::uri]" [HTTP::uri]]"
However, I think that the result will not be what you expect with those combinations, then, as a first shot, you could do like this:
HTTP::respond 302 noserver Location "$new_destination[string range [HTTP::uri] [expr [string len $web_uri]+1] end]"
Anyway, why do you not do that by using "data group" and "class match" to avoid iteration in their arrays? Maybe it could be more easy to do.
https://devcentral.f5.com/wiki/iRules.class.ashx
Another point,is the second part that seems to have the same effect when the operator "equals" and "starts_with", will have the same final execution, then it seems to me to be redundant and unnecessary to use the first operator "equals". Sorry if I did not analyze as a whole.
I think that's all, I hope I have helped you!
Regards.
Hi Eirikn,
I've to second Cjuniors opinion to use [class] instead of [array] for this specific task. The reason for this is, that an [array] can't be easily crawled in a $STRING starts_with [array names] fashion. Well, using a [foreach] loop will work, but its far away from being ideal... 😉
But if you still want to stick with this approach, then you may want to take a look to the iRule below.
It resolves your question be using a [string map -nocase [list $web_uri ""] [HTTP::uri]] and has some additional performance optimizations included (e.g. using RULE_INIT to define the [array]'s not on every request, removed the trailing / slashes from redirect locations, changed the code to use [array names], removed the duplicated execution of [string tolower [HTTP::host]] and finally combined the [if $host_header] statements.
BTW: I duno if a starts_with operator for every $host_header would be sufficient, too?
when RULE_INIT { unset -nocomplain static::pools array set static::pools { sliders.test.example.no pool_example_test bee.test.example.no pool_example_test tinypower.test.example.no pool_example_test tbank.test.example.no pool_example_test bank.test.example.no pool_example_test womvalley.test.example.no pool_example_test redakto- pool_example_redaktor priceapi1-sitecore1.test.example.no pool_example_redaktor } unset -nocomplain static::redirects array set static::redirects { /caf https://banktest.portal.no/dummy-text_to_show-something-web /insurance http://test.dummy.customer.no/example /cfs https://cfs-ws-customer.vendor.no } } when HTTP_REQUEST { foreach web_uri [array names static::redirects] { if { [string tolower [HTTP::uri]] starts_with "$web_uri" } then { HTTP::respond 302 noserver Location "$static::redirects($web_uri)[string map -nocase [list $web_uri ""] [HTTP::uri]]" return } } foreach host_header [array names static::pools] { set low_host [string tolower [HTTP::host]] if { ($low_host equals $host_header) or ($low_host starts_with $host_header) } then { pool $static::pools($host_header) return } } HTTP::respond 200 Content "This site does not exist" }Cheers, Kai
- eirikn
Nimbostratus
Hey guys,
Sorry for the late reply.
I got it working with your help, but eventually we changed the code so we did not need to stringmap rewrite.
Thanks for great input anyway!
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