Persist client on response content with stream

Problem this snippet solves:

Persist a client based on a string found in the response content using a stream profile.

The goal is to find a string in the response payload which is unique to the client session. The rule requires a blank stream profile enabled on the virtual server. This example uses the jsessionid value, but it could be modified to search for any string in the content.

The advantage over this rule using a stream profile versus collecting the response content is that the stream profile should be faster and require fewer resources.

Code :

when HTTP_RESPONSE {   

   # Use persistence based on the same token that was added in a prior response
   # Need to parse $jsessionid from some portion of the request headers or payload
   # See this Codeshare entry for some examples of using cookie or path commands to do so
   # http://devcentral.f5.com/s/wiki/default.aspx/iRules/Weblogic_JSessionID_Persistence.html
   persist $my_jsessionid_parsed_from_the_request 3600

}
when HTTP_RESPONSE {   
   
   # Clear the jsessionid if it exists already on this TCP connection   
   if {[info exists jsessionid]}{   
      unset jsessionid   
   }   
   
   # Only look for the jsessionid in text responses   
   if {[HTTP::header value "Content-Type"] starts_with "text"}{   
   
      log local0. "[IP::client_addr]:[TCP::client_port]: Matched text, enabling stream filter"   
   
      # Because TCL doesn't support lookaheads, match the jsessionid string and value   
      # We'll parse out the value in STREAM_MATCHED 
      # Assume the jsessionid is 1 to 100 characters (terminated by a non-alphanumeric character). 
      STREAM::expression ;jsessionid=[A-Za-z0-9]{1,100}   
      STREAM::enable   
   
      # Enable the STREAM_MATCHED event as it could have been disabled if there was a prior    
      # response on this TCP connection   
      event STREAM_MATCHED enable   
   
   } else {   
   
      # Disable the stream filter as this wasn't a text response   
      log local0. "[IP::client_addr]:[TCP::client_port]: No Content-Type match, disabling stream filter"   
      STREAM::disable   
   }   
}   
when STREAM_MATCHED {   
   
   # Save the matched value (example: ;jsessionid=ABCDEF)   
   set jsessionid [STREAM::match]   
   log local0. "[IP::client_addr]:[TCP::client_port]: Matched: $jsessionid"   
   
   # STREAM::match shouldn't match a null string with the defined regex, but check anyhow 
   if {[string length $jsessionid]}{   
   
      # Get the jsessionid value (split ;jsessionid=ABCDEF on the equals sign)   
      set jsessionid [getfield $jsessionid "=" 2]   
   
      # The iRule parser doesn't allow the persist command in STREAM_MATCHED.     
      # It works though, so hide the command from the parser   
      # Add a persistence record with the jsessionid token and a one hour timeout
      set persist_cmd "persist add uie $jsessionid 3600"   
      log local0. "[IP::client_addr]:[TCP::client_port]: Parsed: $jsessionid \$persist_cmd: $persist_cmd"   
   
      eval $persist_cmd
      #persist add uie $jsessionid

      # Assume the first match is the same as any other jsessionids, so stop checking for them   
      log local0. "[IP::client_addr]:[TCP::client_port]: Added persistence record. Exiting event for this response."   
      event STREAM_MATCHED disable   
   }   
}
Published Mar 18, 2015
Version 1.0

Was this article helpful?