What could you do with your code in 20 Lines or Less? That's the question I like to ask for the DevCentral community, 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. And to answer that question, this week the 20LoL is taking a bit of a different spin. I went digging through the forms, as is my habit when looking for wickedly cool little iRule tidbits, and the community didn't disappoint. I had a few different examples ready to go, and then while reading through one of them a particular notion occurred to me, and I rather enjoyed it, so we'll see what you think.

Digging back into the forums after near a month away it wasn't difficult to find a few examples of cool iRules doing cool iRuley things. This week we've got forum examples ranging from URI restriction to content type filtering. A solid smattering of iRules lending a helping hand to your application's logical flow in only a few lines of code. Without any further delay, let's have at the code:


Restrict access by URI and IP
Community user FlorianM came to the forums with an inquiry relating to combined inspections. They wanted to check both the originating IP of a client request, as well as the request URI to achieve the desired reaction. Fortunately with iRules this is pretty straight forward and easily slides in under the 20 line mark. Thanks go to What Lies Beneathe assist on this one in tightening up the code. All you need to do is search based on one and then create subqueries for the other. In this case using the URI for the initial pass and the IP after that works great, as you can see in the switch below.

   1: when HTTP_REQUEST {
   2:  switch -glob [HTTP::uri] {
   3:   "/error*" {
   4:    if { (([class match [IP::client_addr] equals ipgrouptest]) or ([class match [IP::client_addr] equals ipgrouptest2])) } {
   5:     #If the client IP match the ipgrouptest/2 class we do nothing
   6:    }
   7:    else { HTTP::respond 403 }
   8:   }
   9:   "/example*" {
  10:    if { (([class match [IP::client_addr] equals ipgrouptest]) or ([class match [IP::client_addr] equals ipgrouptest3])) } {
  11:     #If the client IP match the ipgrouptest/3 class we do nothing
  12:    }
  13:    else { HTTP::respond 403 }
  14:   }
  15:  }
  16: }

Auto SSL selection
The title on this one is a bit deceptive. At first I expected to see an iRule toggling SSL on and off or something similar. What the need was, actually, was to force given URLs to SSL, and everything else force to HTTP. Basically there's a particular form or two that the use needs to ensure are encrypted, but most of the site is not yet functioning properly in SSL, so they need to ensure that anything other than that form is pushed back to HTTP. This is done easily with a pair of iRules, one for each VIP (80 and 443), the combined total of lines? Still less than 21. Kudos again go to What Lies Beneath for not only an awesome display name in the forums, but also a handy little snippet to make this work easily.

Port 443 iRule:

   1: when HTTP_REQUEST {
   2:  switch -glob [string tolower [HTTP::uri]] {
   3:   "/giving*" -
   4:   "/formsdisplay.aspx?ekfrm=12884903667" {
   5:    return }
   6:   default {
   7:    HTTP::redirect "http://[HTTP::host][HTTP::uri]" }
   8:  }
   9: }

Port 80 iRule:

   1: when HTTP_REQUEST {
   2:   switch -glob [string tolower [HTTP::uri]] {
   3:     "/giving*" -
   4:     "/formsdisplay.aspx?ekfrm=12884903667" {
   5:       HTTP::redirect "https://[HTTP::host][HTTP::uri]"
   6:     }
   7:   }
   8: }


Gzip filter
Last but not least, the illustrious hoolio slaps together a fine looking and diabolically simple solution to ensure that a particular VIP only allows gzip type requests. This obviously wouldn't be for mass use in production, but if you've got a particular application need that you want to address, this could do it. Of course if you ask me this will likely get modified so that the default case (I.E. no gzip) does something other than directly respond. That's neither here nor there, though, the solution as it stands could be handy if for no other reason than to depict how to easily identify this type of request. Aaron was even so kind as to show us two different ways of doing so, one with if/else, one with switch. Isn't he just swell? Yes, the combined line count is over 20, but that's two separate iRules folks, you'd use one or the other, not both.

   1: when HTTP_REQUEST {
   2:     if { [string tolower [HTTP::header Accept-Encoding]] contains "gzip" or [string tolower [HTTP::header Accept-Encoding]] contains "deflate" } {
   3:         pool Test_pool
   4:         log local0. "Compression enabled, request has been routed [HTTP::header "Accept-Encoding"]"
   5:     } else {
   6:         HTTP::respond 500 Content "PLEASE SEND A GZIP ENABLED REQUEST" noserver Content-Type "text/html" Connection "Close"
   7:         log local0. "Compression disabled, request has NOT been routed [HTTP::header "Accept-Encoding"]: "
   8:     }
   9: }
  11: # or using switch:
  13: when HTTP_REQUEST {
  14:     switch -glob [string tolower [HTTP::header Accept-Encoding]] {
  15:         "*gzip*" -
  16:         "*deflate*" {
  17:             pool Test_pool
  18:             log local0. "Compression enabled, request has been routed [HTTP::header "Accept-Encoding"]"
  19:         }
  20:         default {
  21:             HTTP::respond 500 Content "PLEASE SEND A GZIP ENABLED REQUEST" noserver Content-Type "text/html" Connection "Close"
  22:             log local0. "Compression disabled, request has NOT been routed [HTTP::header "Accept-Encoding"]: "
  23:         }
  24:     }
  25: }