What could you do with your code in 20 Lines or Less? That's the question I ask (almost) every week, and every week I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head.

Digging through the forums this week turned up a couple more great examples of iRules that can fit in the palm of your hand. They’re so cute and cuddly at under 21 lines, but they pack a punch.  It seems there’s more and more to keep up with in the forums these days, which just means more awesomeness to go around. Here are a couple cool bits that I found.

Selective Stream Replacement

http://devcentral.f5.com/Default.aspx?tabid=53&forumid=5&postid=59883&view=topic

Here’s a good example of doing some stream replacement based on URI and content inspection.  If a certain uri comes in there’s some cookie modification done and some content re-writing via stream profile as well.  Very good use of the tools at hand to pack a lot into a small iRule. Thanks go to hoolio for guiding this user along, as with most forum posts these days it seems. ;)

 when HTTP_REQUEST {  

# Initialize a variable to track whether to rewrite the response headers/content
set check_response 0

# Check if the path is correct
if {[HTTP::uri] starts_with "/nilo"} {
# Track that we'll rewrite the response headers and possibly the payload for this app
set check_response 1
}
}
when HTTP_RESPONSE {

# Check if we're potentially rewriting the response headers/payload for this app
if {$check_response}{

# Check if JSESSIONID cookie exists
if {[HTTP::cookie exists JSESSIONID]}{

# Set the path on the cookie to /sdr/nilo so the client will send the cookie in requests for any path
HTTP::cookie path JSESSIONID "/sdr/nilo"
}

# Check if the response is text
if {[HTTP::header value Content-Type] contains "text"} {

# Set the replacement text and enable the stream filter
STREAM::expression {@/nilo/@/sdr/nilo/@}
STREAM::enable

} else {
# Response isn't text, so disable the stream filter
STREAM::disable
}
}
}
 
Connection logging based on IP

Here’s a good example of someone looking to log information about the connection as it passes through the BIG-IP, but only if the connections are being initiated by a given set of IP addresses. This is a pretty realistic use case. Maybe I just want to log traffic from my test servers, etc. Hoolio provides a simple way to grab some detailed info.

 
when CLIENT_ACCEPTED {

# Check the REQ_IP datagroup to see whether this is a client IP address we want to log for
if { [matchclass [IP::remote_addr] equals $::REQ_IP] }{

set log_connection 1

# Get time for start of TCP connection in milliseconds
set tcp_start_time [clock clicks -milliseconds]

# Log the start of a new TCP connection
log "New TCP connection from [IP::client_addr]:[TCP::client_port] to [IP::local_addr]:[TCP::local_port]"
} else {
set log_connection 0
}
}
when HTTP_REQUEST {

# If we're not logging for this client IP, exit this event in this iRule
if {$log_connection != 1}{ return }

# Get time for start of HTTP request
set http_request_time [clock clicks -milliseconds]

# Log the start of a new HTTP request
set LogString "Client [IP::client_addr]:[TCP::client_port] -> [HTTP::host][HTTP::uri]"
log local0. "$LogString (request)"
}

when HTTP_RESPONSE {
# If we're not logging for this client IP, exit this event in this iRule
if {$log_connection != 1}{ return }

# Received the response headers from the server. Log the pool name, IP and port, status and time delta
log local0. "$LogString (response) - pool info: [LB::server] - status: [HTTP::status] \
    (request/response delta: [expr [clock clicks -milliseconds] - $http_request_time]ms)" 
}
when CLIENT_CLOSED {
# If we're not logging for this client IP, exit this event in this iRule
if {$log_connection != 1}{ return }

# Log the end time of the TCP connection
log "Closed TCP connection from [IP::client_addr]:[TCP::client_port] to \
    [IP::local_addr]:[TCP::local_port] (open for: [expr [clock clicks -milliseconds] - $tcp_start_time]ms)" 
}

Custom image caching

If you’ve been looking for a way to set up some customized timeouts on specific cache items, such as jpgs vs. gifs, then this example might be just what you were looking for.  At the very least it’s a good starting point and shows how this kind of logic could be applied to get a very detailed caching setup put together for custom items.

 

when RULE_INIT {
  set ::10_secs 10
  set ::20_secs 20
  set ::one_day 86400
  set ::two_hours 7200
  set ::one_week 604800
}


when HTTP_REQUEST {
  set requested_uri [HTTP::uri]
}


when HTTP_RESPONSE {
  if { $requested_uri ends_with ".jpg" } {
  } elseif { $requested_uri ends_with ".gif" } {
    CACHE::enable
  } else  {

    CACHE::disable
  }
}

There you go, three more bite-sized examples of iRules awesomery (yeah, I said it…awesomery).  Go forth and conquer…with iRules.

#Colin