20 Lines or Less #71: Passing Data, Rate Limiting and Re-Writing

 What could you do with your code in 20 Lines or Less? That's the question I like to ask for the DevCentral community (you know, periodically, sometimes, when Endor aligns with Hoth and there is an eclipse), and every time I go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head.

This installment is no different, in all the right ways. We’re touching on some concepts that we’ve seen before over the years, but they’re definitely things that are useful and worth seeing again. Especially so since some of the ways in which these simple concepts are achieved have changed with the introduction of new versions which bring new commands and functions.

Whether you’re a tried by fire, dyed in the wool iRules black-belt or just looking to get your hands dirty for the first time (perhaps even more so for the latter), the 20 Lines or Less is a great place to dig in and see what people are up to. Code from the community, for the community, doing cool things in short order. Dig it? I dig it.


Passing on Site Data


User kj07208 was looking for a way in which to pass HTTP header data along in an HTTP response, so that the next system in line would be able to see the custom headers. This is great and all, except for two things. 1) in their particular case, ACCESS::respond would make more sense, and 2) HTTP headers aren’t, generally, relayed by browsers. This means that if they’re trying to send a response to a browser in hopes that the custom info distributed in the headers gets relayed along, they’re rolling the dice.

Kevin Stewart, helpful as always, points out that for this particular scenario using a cookie actually makes more sense than a header. He then, naturally, goes on to show some simple code that can accomplish what it is the member is looking for. Handy, easy, and provided for copy and paste goodness…what more could you want? For any of those of you looking to forward along data, here’s a look at cookie generation and insertion along with b64 and URI encoding the data, for good measure.

   1: when HTTP_REQUEST {
   2:   if { [URI::query [HTTP::uri] data] ne "" } {
   3:     set data [b64decode [URI::decode [URI::query [HTTP::uri] data]]]
   4:   }
   5: }
   7: when HTTP_RESPONSE {
   8:   if { [info exists data] } {
   9:     HTTP::cookie insert name "data-from-other-site" value $data
  10:     unset data
  11:   }
  12: }


Source Based Re-Writing


In this post user Patrik Jonsson steps in to help out escgate, who is looking for a way to conditionally re-write either the host, the URI, or both, depending on the inbound client’s IP address. This is something we’ve definitely covered, but taking another look is good, as it’s been a while. Thanks to the built in IP commands this is actually pretty simple, and after a bit of back and forth about requirements, here’s all it takes to get this done for the user. Thanks Patrik!


   1: when HTTP_REQUEST { 
   2:   if { [IP::addr [IP::client_addr] equals] } {
   3:     #Do nothing to forward to the default pool
   4:   } else {
   5:     #Replace the host
   6:     HTTP::header replace Host "www.abc.com"
   7:     set [string tolower [HTTP::uri]]
   8:     #Check if the uri start with /go. If not, replace it with /go.
   9:     if { not $uri starts_with "/go"} {
  10:       HTTP::uri "/go"
  11:     }
  12:   }
  13: }


Client-Based Rate Limiting


Here again, Patrik Jonsson comes to the rescue. This time they’re diving in to help out AllrecipesDCO, which sounds like a tasty thing to do. Come on, it was right there. What AllrecipesDCO was looking to do was cook up a way to stop a particular user from slamming their site with so many requests, crushing their servers’ performance. This is something that BIG-IP does, and does quite well, and Patrik shows off a good way to rate limit. This time they’re doing so based on the client browser’s user agent and IP address combined, which seems as good a method of any for this particular use case. Take a look at the chunk of code necessary to thwart the not so nice behavior that was causing Allrecipes grief.

   1: when RULE_INIT {
   2:   set static::lifetime 60
   3:   set static::requestlimit 10
   4: }
   6: when LB_SELECTED {
   7:   if { [HTTP::header "User-Agent"] contains "Mozilla" } {
   8:     #Add a table entry with a lifetime in seconds of the value of $lifetime.
   9:     table add [IP::client_addr] 1 indefinite $static::lifetime
  10:     if { [table incr [IP::client_addr]] > $static::requestlimit } {
  11:       #If the user has surpassed the request limit the pool member is reselected
  12:       log local0. "This server was selected: [LB::server]"
  13:       LB::reselect
  14:       log local0. "Selected [LB::server]"
  15:     }
  16:   }
  17: }
Published Mar 24, 2014
Version 1.0

Was this article helpful?

No CommentsBe the first to comment