Technical Articles
F5 SMEs share good practice.
cancel
Showing results for 
Search instead for 
Did you mean: 
JRahm
Community Manager
Community Manager

What could you do with your code in 20 Lines or Less?

That's the question we like to ask from, for, and of (feel free to insert your favorite preposition here) the DevCentral community, and every time we do, we go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. Thus was born the 20LoL (20 Lines or Less) series many moons ago. Over the years we've highlighted hundreds of iRules examples, all of which do downright cool things in less than 21 lines of code.

Location Header Rewrite with Non-Standard Port

In the first of two entries in this edition of 20LoL from community member AMG, this solution rewrites the location header not just from http to https, but also replaces the non-standard port as well, featuring a command completely valid but underused in lreplace.

when HTTP_RESPONSE {
  if {[string tolower [HTTP::header Location]] starts_with "http://" }{
    #Splits the Location Header string into a list
    # e.g. http://www.test.com/path1/path2/index.html = 'http:', '', 'www.test.com', 'path1', 'path2', 'index.html'
    set loc_list [split [HTTP::header Location] "/"]
    [getfield [HTTP::header Location] "/" 2]
    
    # Replaces list location 0 (first item) with 'https:'
    # e.g. list item 0 = 'http:' and is replaced with 'https:'
    lreplace [$loc_list 0 0 "https:"]
    
    # Appended the port number to list location 2 (the FQDN), if a port is already defined this will replaced
    # e.g. list item 2 = 'www.test.com:897' is replaced with 'www.test.com:80'
    # e.g. list item 2 = 'www2.test.com' is replaced with 'www2.test.com:80'
    lreplace [$loc_list 2 2 [lindex [split [lindex $loc_list 2] ":"] 0]:80]
    
    # List items are joined back together with '/' inserted and set at the new HTTP Location Header
    # e.g. list = 'https:', '', 'www.test.com:80', 'path1', 'path2', 'index.html' becomes 'https://www.test.com:80/path1/path2/index.html'
    HTTP::header replace Location [join $loc_list "/"]
  }
}

Persist on First Address in X-Forwarded-For Header

AMG’s second entry is short but useful extraction of one (in this case the first) of potentially many IP addresses listed in the X-Forwarded-For header for persistence. If the XFF header is empty, then the persistence is mapped to the source address of the IP packet.

# Name: persist_xff_uie
#
# To be used with UIE Persistence Profile
#
# Checks HTTP Request for 'X-Forwarded-For' header and if exists takes the first 'X-Forwarded-For' IP address as sets as
# Persist identifier.
# If the 'X-Forwarded-For' header does not exist then the client IP address is set as Persist identifier.
 
when HTTP_REQUEST {
  if {[HTTP::header X-Forwarded-For] != ""} then {
    persist uie [lindex [split [HTTP::header X-Forwarded-For] ","] 0]
  } else {
      persist uie [IP::client_addr]
  }
}

Select Specific Pool Member via Query Parameter

The first two entries are both in the codeshare, but the final entry is from the answers section of the site, courtesy of a question from community member “Just Have to Know” (cool handle!). The question is how to ensure a request is mapped to a specific pool member. Member Stanislas provides a short and elegant solution utilizing a query parameter on the request URL.

when CLIENT_ACCEPTED {
  set default_pool [LB::server pool]
}
when HTTP_REQUEST {
  set target_member [URI::query [HTTP::uri] server]
  if {!($target_member eq "")} {
    pool $default_pool member $target_member
    HTTP::uri [string map -nocase [list "&server=$target_member" "" ] [HTTP::uri]]
  }
}

And there it is, another edition of 20 Lines or Less, the power of iRules on full display. Happy coding out there, and I look forward to seeing what excellent contributions might make the next edition!

Comments
Kevin_Davies_40
Nacreous
Nacreous
Typo, last iRule, line 8, that should be string map
JRahm
Community Manager
Community Manager
not so fast my friend, "tring map" is the latest and greatest! 🙂 I kid...nice catch.
B_Earp
Nimbostratus
Nimbostratus

First iRule: line 10: set loc_list [lreplace $loc_list 0 0 https:] line 15: set loc_list [lreplace $loc_list 2 2 [lindex [split [lindex $loc_list 2] ":"] 0]:8443]

 

JRahm
Community Manager
Community Manager

Thanks B.Earp, I updated these, but left :80 as the original author has notes in the codeshare entry to change that to whatever the port should be in their scenario. Updated the original in the codeshare entry as well.

 

Version history
Last update:
‎28-Oct-2015 08:00
Updated by:
Contributors