Weblogic JSessionID Persistence
 Problem this snippet solves:  Contributed by: unRuleY, Summarized by: deb 
 Note: The previous version of this iRule contained escaped newlines following the session command, which in versions 10.0 -...
Published Mar 18, 2015
Version 1.0unRuleY_95363
Historic F5 Account
Joined September 25, 2004
unRuleY_95363
Historic F5 Account
Joined September 25, 2004
jurgenvdmark_14 Nimbostratus
Nimbostratus
Oct 23, 2017Weblogic persistence with JSessionID with max lifetime
I've added some functionality to the rule by adding a lifetime as a max session time to the rule. The company I work for requested this functionality in order to simplify maintenance because persistent connections tend to never timeout.
The lifetime is enabled by using a table with a lifetime. If either the persist record doesn't exist or the lifetime is exceeded for the table entry, the session is invalidated by removing all cookies. I've used an iFile for the idle/lifetime exceeded message.
I've replaced all _ with _ for the JsessionID because if the JSessionID starts with a "_" this is interpreted as an option for the table command by TCL.
ltm rule persist_jsessionid {
    when HTTP_REQUEST {
         set to 0 to disable debug logging, 1 to enable
        set DEBUG 1
         set idle timeout and session lifetime, for now the values are set directly in the iRule
        set IDLE 1800
        set TTL 36000
         used for logging src_ip/src_port, virtual
        set PREFIX "src_ip=[IP::client_addr], src_port=[TCP::client_port], virtual=[virtual name] : "
         log HTTP-request and Cookies header
        if { ${DEBUG} == 1 } { 
            log local0.debug "${PREFIX}[HTTP::method] [HTTP::uri] HTTP/[HTTP::version]" }
            log local0.debug "Cookie: [HTTP::header Cookie]"
        }
        set STATE ""
        set JSESSIONID [string map { \- \_ } [string tolower [HTTP::cookie value "JSESSIONID"]]]
        if { ${JSESSIONID} eq "" } {
             JSESSIONID Cookie wasn't set or didn't have a value, so check for the cookie in the URI
            set JSESSIONID [string map { \- \_ } [findstr [string tolower [HTTP::path]] "jsessionid=" 11 ";" ]]
        }
        if { ${JSESSIONID} neg "" } {
             read remaining session lifetime
            set LIFETIME [ table lifetime -subtable cookie -remaining "${JSESSIONID}" ]
            if { ${LIFETIME} eq "" || ${LIFETIME} == -1 } {
                 lifetime exceeded, delete persistency data and cookie
                set STATE "expired"
                persist delete uie "${JSESSIONID}"
                if { ${DEBUG} == 1 } { log local0.debug "${PREFIX}state=expired, jsessionid=${JSESSIONID}" } 
            } elseif { [persist lookup uie "${JSESSIONID}"] eq "" } {
                 idle timeout, delete table entry 
                set STATE "idle"
                table delete -subtable cookie "${JSESSIONID}"
                if { ${DEBUG} == 1 } { log local0.debug "${PREFIX}state=idle, jsessionid=${JSESSIONID}" } 
            } else {
                persist uie "${JSESSIONID}" ${IDLE}
                if { ${DEBUG} == 1 } { log local0.debug "${PREFIX}state=persist. jsessionid=${JSESSIONID}, remaining=${LIFETIME}, persist=\"[persist lookup uie "${JSESSIONID}"]\"" }
            }
        }
         check if state is idle or expired
        if { ${STATE} eq "idle" || ${STATE} eq "expired" } { 
             Erase cookies
            set SETCOOKIES ""
            foreach COOKIE_NAME [HTTP::cookie names] { 
                set SETCOOKIES "${SETCOOKIES}\r\nSet-Cookie: ${COOKIE_NAME}=; path=/; expires=Thu, 01-Jan-1970 01:00:00 GMT"
            }
            if { ${DEBUG} == 1 } { log local0.debug "${PREFIX}Session expired, action=delete, ${SETCOOKIES}" }
             Respond to client
            set CONTENT [ifile get "/Common/timeout.html"]
            HTTP::respond 200 content ${CONTENT} Cache-Control "no-cache" Set-Cookie ${SETCOOKIES}
        }
    }
    when LB_SELECTED {
        if { ${DEBUG} == 1 } { log local0.debug "${PREFIX}Pool_member=[LB::server addr]" }
    }
    when HTTP_RESPONSE {
         check if the jsessionid cookie is present in the response and has a non-null value
        set JSESSIONID [string map { \- \_} [string tolower [HTTP::cookie value "JSESSIONID"]]]
        if { ${JSESSIONID} ne "" } {
             Persist on the session cookie value for IDLE time
            persist add uie "${JSESSIONID}" ${IDLE}
            if { ${DEBUG} == 1 } { log local0.debug "${PREFIX}action=persist, jsessionid=${JSESSIONID}, idletime=${IDLE}, persist=\"[persist lookup uie "${JSESSIONID}"]\"" } 
             set lifetime for cookie
            table set -subtable cookie "${JSESSIONID}" "[persist lookup uie "${JSESSIONID}"]" indefinite ${TTL}
            if { ${DEBUG} == 1 } { log local0.debug "${PREFIX}action=add, jsessionid=${JSESSIONID}, table=cookie, lifetime=${TTL}" }
        }
    }
}