ASP Session ID Persistence

Problem this snippet solves:

Persist on ASP SessionID cookie value or PID. Some ASP applications set a session cookie named "ASPSESSIONIDxxx" where "xxx" completes the 20 character alpha string dynamically generated from the process ID of the IIS instance. The cookie name will be constant for the life of the instance and unique to that instance, and will be used for all cookies set by that instance. When an instance is restarted, the PID changes and consequently the dynamic string changes, and the connection must be re-load balanced. Other ASP applications use a session cookie named "ASP.NET_SessionId". This cookie name does not change for these applications. Persistence can be based off of the cookie name as a whole, or just the dynamic part of the string. There are a few advantages to using the PID string instead of the cookie value: the cookie name changes less frequently compared with the cookie value you don't have to worry about the client changing the cookie value you only have one persistence record per web server instance instead of one per client The 2 examples below demonstrate both solutions, along with a few variations for implementing the desired persistence: One uses "session" commands and direct node selection with LB_FAILED recovery logic, the other uses "persist" commands which manage node selection and recovery more automatically.

Code :

### iRule source with persist command ###
when RULE_INIT {
  set ::debug 0
}
when HTTP_REQUEST {
  set cli [IP::remote_addr]:[TCP::remote_port]
  set SessionId [HTTP::cookie ASP.NET_SessionId]
  if {$::debug}{log local0. "Client: $cli  Request SessionId: >$SessionId<"}
  if { $SessionId ne "" } { persist uie $SessionId 1800 }
}
when LB_SELECTED {
  if {$::debug}{log local0. "Client: $cli  LB to:  [LB::server addr]"}
}
when HTTP_RESPONSE {
  set SessionId [HTTP::cookie ASP.NET_SessionId]
  if {$::debug}{log local0. "Client: $cli  Response SessionId: >$SessionId<"}
  if { $SessionId ne "" }{ persist add uie $SessionId 1800 }
}

### iRule source with session command ###
when RULE_INIT {
  set ::debug 0
}
when HTTP_RESPONSE {
  set sessionID ""
  set sessionID [findstr [HTTP::cookie names] "ASPSESSIONID" 12 20]]
  set persistTo [session lookup uie $sessionID]
  if { $persistTo equals "" } {
    session add uie $sessionID [IP::server_addr] 1800
    if {$::debug}{log local0. "added server entry $persistTo for aspsessionID $sessionID"}
  } else {
    if {$::debug}{log local0. "existing server entry $persistTo for aspsessionID $sessionID"}
  }
}
when HTTP_REQUEST {
  set sessionID ""
  set sessionID [findstr [HTTP::cookie names] "ASPSESSIONID" 12 20]]
  set persistTo [session lookup uie $sessionID]
  if { $persistTo equals "" } {
    pool [LB::server pool]
    if {$::debug}{log local0. "No aspsession ID, load balancing the connection."}
  } else {
    pool [LB::server pool] member $persistTo
    if {$::debug}{log local0. "aspsessionID $sessionID sent to $persistTo"}
  }
}
when LB_FAILED {
  # If no servers are active, redirect to sorry page elsewhere
  if {[active_members [LB::server pool]] == 0}{
    HTTP::redirect http:://sorry.domain.com/NoServersAvail.html
    if {$::debug}{log local0. "No servers available. Redirecting to sorry server."}
  } else {
    LB::detach
    LB::reselect [LB::server pool]
    if {$::debug}{log local0. "LB failed, re-load balancing to pool."}
 }
}

Tested this on version:

9.0
Published Jan 30, 2015
Version 1.0