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!
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