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.

Generally speaking the 20LoL just displays three randomly cool iRule examples. This time around, however, I'm going with a bit of a theme. The theme comes from one of the posts I was going to discuss anyway, as it was the center of the question being asked. The user was looking for help properly using the "or" (||) syntax within an if statement. A couple of examples were given, each correct in their own right, and it was immediately apparent that there were three complete separate and equally viable and accurate ways of accomplishing what was being asked, without any Tcl backflips or manipulation. The whole timtowtdi (there is more than one way to do it) slogan rang in my ears, and suddenly I was compelled to discuss each option here at least briefly, and display them. So that's where we're at this week, inspecting the different ways to deal with a logical "or" within a brief iRule. All of the ideas are pulled from the same thread (https://devcentral.f5.com/Community/GroupDetails/tabid/1082223/asg/50/aft/2164664/showtab/groupforums/Default.aspx), though only two of the examples were given. The third I wrote up briefly as a illustration of the third or mechanism to be discussed.

First, a traditional approach
In the original post the user was looking to use the traditional "or" statement (written as either "or" or "||") to inspect a URI and perform the same action for either of two possible outcomes. This is straight-forward and is exactly the kind of thing that the "or" statement was created for back in the stone-age days of programming. With a couple of tweaks to syntax to side-step some errors in the originally outset code, this example was laid out and would work quite nicely to achieve the goal.

   1: when HTTP_REQUEST {
   2:     if { ([HTTP::uri] starts_with "/path/to/broken") || ([HTTP::uri] starts_with "/other/path/broken") } {
   3:         HTTP::redirect "maintenance.html"
   4:         #Note: Modified URL for forum posting.
   5:     }
   6: }


Next, we switch it up
There was some discussion in the thread, and a couple of other options were levied as viable. First we'll look at the more obvious approach using the switch command. Switch has a built in "or" functionality by using the dash ("-") after a given match criteria. In this way it's extremely easy to have multiple different match criteria perform the same action, which is exactly the same as the above stated logical "or" command used outright. It's far cleaner, too, when dealing with more than just a single "or". If you're going to have multiple matches all pointing to the same action, do yourself a favor and use this approach.

 

   1: when HTTP_REQUEST {
   2:     switch -glob [HTTP::uri] {
   3:         "/path/to/broken*" - 
   4:         "/other/path/broken*" {
   5:             HTTP::redirect "/maintenance.html"
   6:         }
   7:     }
   8: }


Lastly we show a classy way to go about things
Classes, or data groups, might not not seem like a go-to choice when it comes to an "or" style match. Sure, they are great for specific matches, but that's more of an "equals" kind of thing, isn't it? What if you want to match multiple options, do you loop through the class match several times? Well..no, as a matter of fact you're really doing an "or" any time you use a class match, it's just about the perspective you're taking and how you make use of the class. Sure, you could assign each key in the class unique values and have them returned and acted upon based on the class match. This is precise and exacting, and each key would then end up with a different outcome, perhaps. But what if you just have a class with 2 or more keys in it, and perform the same action to the connection if the URI matches any of the values in the class? To write out the pseudo-code it would sound something like "If the URI matches the first entry in the class, or the second entry, or the third entry….perform action x". Well…there's your "or" right there. So a data group is a fine choice for an "or" and, depending on your needs, may well be your best option as it scales efficiently both in readability and performance. An example would look as simple as below, though of course it would require a string type data group created with keys matching the URIs that you wanted to perform the redirect for.

   1: when HTTP_REQUEST {
   2:   if {[class match [HTTP::uri] equals myUris]} {
   3:     HTTP::redirect "/maintenance.html"
   4:   }
   5: }

With three more interesting iRules out there to feast your eyes on, I hope you've enjoyed this week's 20LoL. If this format is interesting, drop me a line and let me know. I'm always a fan of feedback and suggestions. Until next time, code hard.