HTTP Session Watcher

Problem this snippet solves:

iRule to capture and display HTTP request and response headers (and optionally request payload) for HTTP sessions flowing through the BIG-IP

How to use this snippet:

Screenshots

Code :

### HTTP Session Watcher
### Chad Jenison - c.jenison -at- f5.com 
### version 1.0
### A tool to record and show HTTP Sessions and their underlying requests and response headers (and response payload) on a BIG-IP
### Notes: 
### This rule utilizes a non-trivial amount of table memory and does a pretty good amount of data-plane processing for saving traffic flow data.
### For that reason, you probably want to be careful about deploying it on production virtual servers and begin with your same app/pool on a test virtual server with this iRule enabled
### If you decide to migrate this to a production virtual server, you probably want to take advantage of the options available in RULE_INIT for limiting the traffic the rule captures
### This was tested on BIG-IP 10.2
### The most reliable codepath is to let the rule use its own cookie; use of an external (app) cookie is intended to not impact traffic and reveal use of the tool 
### BIG-IP Generated Redirects are not captured; but do not cause application misbehavior
### Use of the rule on both an HTTP and HTTPS virtual server for the same session has not been tested and likely doesn't work yet. Will fix later.
### Not yet tested with BIG-IP ASM,WA,APM enabled on virtual server
### Textual HTTP Response Status is not displayed; in spite of its presence in the HTTP response. Couldn't find iRule API to access this; only numeric response status
### To-Do: 
### Support combined HTTP&HTTPS access to the same app with session visibility provided in a protocol independent manner
### Clean-Up table display using stylesheets
### Add cr-lf's to raw HTTP request display
### Support HTTP Request Payload Capture
### Escape HTTP Response Payload for display

when RULE_INIT {
# If you want to use existing application session cookie as basis for tracking provide cookie name here
  set static::externalcookiename "JSESSIONID"
# By default this rule uses its own cookie; change this to 1 if using external cookie above
  set static::useexternalcookie 0
# Cookie Name if inserting rule-specific tracking cookie
  set static::trackingcookie "BIGIPHTTPWATCHER"
# If you want to enable IP-based restrictions on session capture, set this static variable to 1
  set static::enablesourceipfilter 0
# NOTE Provide enabled source IP networks in iRule datagroup named "enablednetworks"
# Also, we can capture based on presence of an HTTP request header; set this variable to 1 to enable this restriction
  set static::enablecaptureonheaderpresent 0
  set static::magiccaptureheader "x-bigipsession-capture"
# Also, we can capture based on substring match in User-Agent string; uncomment to enable this restriction
#  set static::useragentmagicstring "bigipsession-capture"
#  set static::useragentmagicstring "Chrome"
# This iRule consumes a lot of processing resources as well as table memory. HTTP response payload is likely the biggest consumer of memory; to disable, set this variable to 1
  set static::disableresponsepayloadcapture 1
# With respect to the memory utilization problem, it also makes sense to set a shorter timeout on the response payload table entries; defaulting to 120 seconds
  set static::responsepayloadtabletimeout 120
## tableentrytimeout in seconds (3600 is one hour)
  set static::tabletimeout 3600
  set static::responsedatalimit 1048576
  if {$static::useexternalcookie} {
    set static::sessioncookie $static::externalcookiename
  } else {
    set static::sessioncookie $static::trackingcookie
  }
  set static::enablemagicurlviewing 1
  set static::magicurlprefix "/f5/bigiphttpwatcher"
  set static::htmlstart "BIG-IP HTTP Session Watcher"
  set static::htmlend ""
}



when CLIENT_ACCEPTED {
  set disablecapture 0
  if {$static::enablesourceipfilter} {
    if {[matchclass [IP::client_addr] equals $::enablednetworks]} {
      #log local0. "Client IP filtering enabled and Client IP matched"
    } else {
      #log local0. "Client IP filtering enabled and Client IP did not match"
      set disablecapture 1
    }
  }
}

# this code implements the session browsing UI and is given a priority of 501 because it doesn't need special early access to the HTTP Request
# performance optimization is not a focus for this code, given that it's just powering the UI
when HTTP_REQUEST priority 501 {
  if {$static::enablemagicurlviewing} {
    if {[HTTP::uri] starts_with $static::magicurlprefix} {
      set magicrequest 1
      log local0. "BIG-IP HTTP Watcher UI Access from [IP::client_addr]"
      set parsedsession [URI::query [HTTP::uri] "session"]
      if {$parsedsession eq ""} {
        set sessionbody {

F5 BIG-IP HTTP Watcher


SessionList


} foreach session [table keys -subtable requestcounter] { set requestcount [table lookup -subtable requestcounter $session] set sessionline "" append sessionbody $sessionline } append sessionbody "
Session IDRequest CountUser Agent (most recent)Source IP(most recent)
" append sessionline $session append sessionline "" append sessionline $requestcount append sessionline "" append sessionline [table lookup -subtable requestheaderUser-Agent $session$last] append sessionline "" append sessionline [table lookup -subtable clientip $session$last] append sessionline "
" set htmlresponse $static::htmlstart$sessionbody$static::htmlend } else { set rawrequest [URI::query [HTTP::uri] "rawrequest"] set rawrequestsent [URI::query [HTTP::uri] "rawrequestsent"] set payload [URI::query [HTTP::uri] "payload"] set parsedrequestnumber [URI::query [HTTP::uri] "requestnumber"] if {$rawrequest eq 1} { set responsebody [table lookup -subtable rawrequest $parsedsession$parsedrequestnumber] set htmlresponse $static::htmlstart$responsebody$static::htmlend } elseif {$payload eq 1} { set htmlresponse [table lookup -subtable responsepayload $parsedsession$parsedrequestnumber] } else { ##we got a session param in the URL, so render requests from the table set requestbody {} ## this for loop will iterate over each request associated with the session, outputting a table row for each request for {set requestnumber 1} {$requestnumber <= [table lookup -subtable requestcounter $parsedsession]} {incr requestnumber} { set requestentry "" append requestbody $requestentry } set htmlresponse $static::htmlstart$requestbody$static::htmlend } } HTTP::respond 200 content $htmlresponse Cache-Control No-Cache Pragma No-Cache } } } when HTTP_REQUEST priority 1 { ## this block of code does all the work of saving HTTP request data to the table structure set magicrequest 0 if {[HTTP::uri] starts_with $static::magicurlprefix} { set magicrequest 1 } if {!$magicrequest} { ## here we're going to decide whether we should cature request to table # we're going to detect a $disablecapture variable and if it's already been set (for example based on the user's client IP not matching allowed networks) don't even bother further evaluation of restrictions if {!$disablecapture} { if {$static::enablecaptureonheaderpresent} { if {[HTTP::header exists $static::magiccaptureheader]} { #log local0. "magic capture header required and is present" } else { #log local0. "magic capture header required and is missing" set disablecapture 1 } } if {[info exists static::useragentmagicstring]} { if {[HTTP::header User-Agent] contains $static::useragentmagicstring} { #log local0. "User-Agent magic string required and present; will capture this request" } else { #log local0. "User-Agent magic string required and not present; disabling capture" set disablecapture 1 } } } if {!$disablecapture} { ##code to do transaction logging is here set nocookie 1 if {[HTTP::cookie exists $static::sessioncookie]} { set nocookie 0 set sessionid [HTTP::cookie $static::sessioncookie] } else { #This code is generating a session cookie value - found on devcentral post by Robert Sutcliffe set rnum [format "%08X" [expr { int(1000000000 * rand() ) } ] ] set cthash [format "%08X" [clock clicks -milliseconds] ] set sessionid "$cthash$rnum" } set requestnumber [table incr -subtable requestcounter -mustexist $sessionid] if {$requestnumber eq ""} { table set -subtable requestcounter $sessionid 1 $static::tabletimeout set requestnumber 1 } #Here is where we store request attributes to table for later viewing table set -subtable rawrequest $sessionid$requestnumber [HTTP::request] $static::tabletimeout table set -subtable clienturi $sessionid$requestnumber [HTTP::uri] $static::tabletimeout table set -subtable clientmethod $sessionid$requestnumber [HTTP::method] $static::tabletimeout table set -subtable clienthttpver $sessionid$requestnumber [HTTP::version] $static::tabletimeout table set -subtable clientrequests $sessionid$requestnumber [HTTP::request] $static::tabletimeout table set -subtable httpreqnum $sessionid$requestnumber [HTTP::request_num] $static::tabletimeout table set -subtable requestheadernames $sessionid$requestnumber [HTTP::header names] $static::tabletimeout foreach header [HTTP::header names] { table set -subtable requestheader$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout } table set -subtable clientip $sessionid$requestnumber [IP::client_addr] $static::tabletimeout table set -subtable clientport $sessionid$requestnumber [TCP::client_port] $static::tabletimeout table set -subtable vsip $sessionid$requestnumber [IP::local_addr] $static::tabletimeout table set -subtable vsport $sessionid$requestnumber [TCP::local_port clientside] $static::tabletimeout table set -subtable vsname $sessionid$requestnumber [virtual] $static::tabletimeout table set -subtable cmpunit $sessionid$requestnumber [TMM::cmp_unit] $static::tabletimeout } } } when HTTP_REQUEST_SEND priority 501 { #log local0. "disablecapture: $disablecapture" if {!$disablecapture && !$magicrequest} { clientside { table set -subtable requesturisent $sessionid$requestnumber [HTTP::uri] $static::tabletimeout table set -subtable requestheadernamessent $sessionid$requestnumber [HTTP::header names] $static::tabletimeout table set -subtable requestmethodsent $sessionid$requestnumber [HTTP::method] $static::tabletimeout table set -subtable requesthttpversent $sessionid$requestnumber [HTTP::version] $static::tabletimeout foreach header [HTTP::header names] { table set -subtable requestheadersent$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout } } # table set -subtable sentrawrequest $sessionid$requestnumber [HTTP::request] $static::tabletimeout set requestsendtime [clock clicks -milliseconds] } } when HTTP_RESPONSE priority 1 { set dontcaptureresponse 0 set deleterequestentries 0 if {!$disablecapture} { set responsestarttime [clock clicks -milliseconds] # Trigger collection for up to configured limit of response data if {!$static::disableresponsepayloadcapture} { if {[HTTP::header exists "Content-Length"] && [HTTP::header "Content-Length"] <= $static::responsedatalimit}{ set content_length [HTTP::header "Content-Length"] } else { set content_length $static::responsedatalimit } # Check if $content_length has been set and is not set to 0 if { [info exists content_length] && $content_length > 0} { HTTP::collect $content_length } } # we have a serious of if/elseif/else here to deal with the possibilities regarding session cookie usage # *** this scenario below is when the rule itself is going to set a cookie because the request doesn't contain one if {$nocookie && !$static::useexternalcookie} { #code will insert a cookie into 1st response if we are not using external cookie and response didn't contain the cookie HTTP::cookie insert name $static::sessioncookie value $sessionid } elseif {[HTTP::cookie exists $static::sessioncookie]} { # *** this scenario below is used when we detect the server setting an external session cookie #we're hoping to find the server issuing a set-cookie right here for the external session cookie being used if {$requestnumber eq 1} { # We're here because this is a first hit and we are seeing the server do a set-cookie set deleterequestentries 1 } else { # We're here because the server is doing a set-cookie for the session cookie and it's not the first request # we want to avoid destroying the old table entries # and let's populate the old session's final request with the response we see here (it'll also be added to the new session's first request entry) table set -subtable responsestatus $sessionid$requestnumber [HTTP::status] $static::tabletimeout table set -subtable responseheadernames $sessionid$requestnumber [HTTP::header names] $static::tabletimeout table set -subtable serverip $sessionid$requestnumber [IP::server_addr] $static::tabletimeout table set -subtable serverport $sessionid$requestnumber [TCP::server_port] $static::tabletimeout table set -subtable serversideip $sessionid$requestnumber [IP::local_addr] $static::tabletimeout table set -subtable serversideport $sessionid$requestnumber [TCP::local_port] $static::tabletimeout table set -subtable httprespnum $sessionid$requestnumber [HTTP::request_num] $static::tabletimeout table set -subtable responsestartdelay $sessionid$requestnumber [expr {$responsestarttime - $requestsendtime}] $static::tabletimeout foreach header [HTTP::header names] { table set -subtable responseheader$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout } } set newrequestnumber 1 set priorsessionid $sessionid set sessionid [HTTP::cookie $static::sessioncookie] table set -subtable requestcounter $sessionid 1 $static::tabletimeout # this code will migrate request table entries to use the new external session cookie value as key and then delete the table entries using the (temp) priorsessionid as key table set -subtable rawrequest $sessionid$newrequestnumber [table lookup -subtable rawrequest $priorsessionid$requestnumber] $static::tabletimeout table set -subtable clienturi $sessionid$newrequestnumber [table lookup -subtable clienturi $priorsessionid$requestnumber] $static::tabletimeout table set -subtable clientmethod $sessionid$newrequestnumber [table lookup -subtable clientmethod $priorsessionid$requestnumber] $static::tabletimeout table set -subtable clienthttpver $sessionid$newrequestnumber [table lookup -subtable clienthttpver $priorsessionid$requestnumber] $static::tabletimeout table set -subtable clientrequests $sessionid$newrequestnumber [table lookup -subtable clientrequests $priorsessionid$requestnumber] $static::tabletimeout table set -subtable httpreqnum $sessionid$newrequestnumber [table lookup -subtable httpreqnumber $priorsessionid$requestnumber] $static::tabletimeout table set -subtable requestheadernames $sessionid$newrequestnumber [table lookup -subtable requestheadernames $priorsessionid$requestnumber] $static::tabletimeout foreach header [table lookup -subtable requestheadernames $priorsessionid$requestnumber] { table set -subtable requestheader$header $sessionid$newrequestnumber [table lookup -subtable requestheader$header $priorsessionid$requestnumber] $static::tabletimeout } table set -subtable clientip $sessionid$newrequestnumber [table lookup -subtable clientip $priorsessionid$requestnumber] $static::tabletimeout table set -subtable clientport $sessionid$newrequestnumber [table lookup -subtable clientport $priorsessionid$requestnumber] $static::tabletimeout table set -subtable vsip $sessionid$newrequestnumber [table lookup -subtable vsip $priorsessionid$requestnumber] $static::tabletimeout table set -subtable vsport $sessionid$newrequestnumber [table lookup -subtable vsport $priorsessionid$requestnumber] $static::tabletimeout table set -subtable vsname $sessionid$newrequestnumber [table lookup -subtable vsname $priorsessionid$requestnumber] $static::tabletimeout table set -subtable cmpunit $sessionid$newrequestnumber [table lookup -subtable cmpunit $priorsessionid$requestnumber] $static::tabletimeout table set -subtable requesturisent $sessionid$newrequestnumber [table lookup -subtable requesturisent $priorsessionid$requestnumber] $static::tabletimeout table set -subtable requestheadernamessent $sessionid$newrequestnumber [table lookup -subtable requestheadernamessent $priorsessionid$requestnumber] $static::tabletimeout table set -subtable requestmethodsent $sessionid$newrequestnumber [table lookup -subtable requestmethodsent $priorsessionid$requestnumber] $static::tabletimeout table set -subtable requesthttpversent $sessionid$newrequestnumber [table lookup -subtable requesthttpversent $priorsessionid$requestnumber] $static::tabletimeout foreach header [table lookup -subtable requestheadernamessent $priorsessionid$requestnumber] { table set -subtable requestheadersent$header $sessionid$newrequestnumber [table lookup -subtable requestheadersent$header $priorsessionid$requestnumber] $static::tabletimeout } set requestnumber 1 } elseif {$nocookie} { # lacking cookie in request and cookie not being set in response; we'll avoid capturing response and delete the initial request table entries set dontcaptureresponse 1 set deleterequestentries 1 set priorsessionid $sessionid } if {!$dontcaptureresponse} { table set -subtable responsestatus $sessionid$requestnumber [HTTP::status] $static::tabletimeout table set -subtable responseheadernames $sessionid$requestnumber [HTTP::header names] $static::tabletimeout table set -subtable serverip $sessionid$requestnumber [IP::server_addr] $static::tabletimeout table set -subtable serverport $sessionid$requestnumber [TCP::server_port] $static::tabletimeout table set -subtable serversideip $sessionid$requestnumber [IP::local_addr] $static::tabletimeout table set -subtable serversideport $sessionid$requestnumber [TCP::local_port] $static::tabletimeout table set -subtable httprespnum $sessionid$requestnumber [HTTP::request_num] $static::tabletimeout table set -subtable responsestartdelay $sessionid$requestnumber [expr {$responsestarttime - $requestsendtime}] $static::tabletimeout foreach header [HTTP::header names] { table set -subtable responseheader$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout } } if {$deleterequestentries} { # we're deleting HTTP request table entries (and presumably the value of requestnumber is 1) table delete -subtable rawrequest $priorsessionid$requestnumber table delete -subtable clienturi $priorsessionid$requestnumber table delete -subtable clientmethod $priorsessionid$requestnumber table delete -subtable clienthttpver $priorsessionid$requestnumber table delete -subtable clientrequests $priorsessionid$requestnumber table delete -subtable httpreqnum $priorsessionid$requestnumber foreach header [table lookup -subtable requestheadernames $priorsessionid$requestnumber] { table delete -subtable requestheader$header $priorsessionid$requestnumber } table delete -subtable requestheadernames $priorsessionid$requestnumber table delete -subtable clientip $priorsessionid$requestnumber table delete -subtable clientport $priorsessionid$requestnumber table delete -subtable vsip $priorsessionid$requestnumber table delete -subtable vsport $priorsessionid$requestnumber table delete -subtable vsname $priorsessionid$requestnumber table delete -subtable cmpunit $priorsessionid$requestnumber table delete -subtable requesturisent $priorsessionid$requestnumber table delete -subtable requestheadernamessent $priorsessionid$requestnumber table delete -subtable requestmethodsent $priorsessionid$requestnumber table delete -subtable requesthttpversent $priorsessionid$requestnumber foreach header [HTTP::header names] { table delete -subtable requestheadersent$header $priorsessionid$requestnumber } table delete -subtable requestcounter $priorsessionid } } } when HTTP_RESPONSE_DATA { if {!$disablecapture} { #record time set responsercvtime [clock clicks -milliseconds] #store payload to table table set -subtable responsepayload $sessionid$requestnumber [HTTP::payload] table set -subtable responsercvdelay $sessionid$requestnumber [expr {$responsercvtime - $requestsendtime}] $static::responsepayloadtabletimeout } }
Request NumberBIG-IP InfoHTTP Request(received from client)HTTP Request(sent to server)HTTP Response
" append requestentry "$requestnumber" append requestentry "Raw Request Rcvd" set responsepayload [table lookup -subtable responsepayload $parsedsession$requestnumber] if {$responsepayload eq ""} { } else { append requestentry "Response Payload" } append requestentry "" append requestentry "Client IP & Port: " append requestentry [table lookup -subtable clientip $parsedsession$requestnumber] append requestentry ":" append requestentry [table lookup -subtable clientport $parsedsession$requestnumber] append requestentry "" append requestentry "Client IP & Port(Server-side): " append requestentry [table lookup -subtable serversideip $parsedsession$requestnumber] append requestentry ":" append requestentry [table lookup -subtable serversideport $parsedsession$requestnumber] append requestentry "" append requestentry "Virtual Server IP & Port: " append requestentry [table lookup -subtable vsip $parsedsession$requestnumber] append requestentry ":" append requestentry [table lookup -subtable vsport $parsedsession$requestnumber] append requestentry "" append requestentry "Server IP & Port: " append requestentry [table lookup -subtable serverip $parsedsession$requestnumber] append requestentry ":" append requestentry [table lookup -subtable serverport $parsedsession$requestnumber] append requestentry "Virtual Name: " append requestentry [table lookup -subtable vsname $parsedsession$requestnumber] append requestentry "CMP Unit: " append requestentry [table lookup -subtable cmpunit $parsedsession$requestnumber] append requestentry "HTTP Req Num on Socket: " append requestentry [table lookup -subtable httpreqnum $parsedsession$requestnumber] append requestentry "HTTP Resp Num on Socket: " append requestentry [table lookup -subtable httprespnum $parsedsession$requestnumber] append requestentry "Client IP Continent: " append requestentry [whereis [table lookup -subtable clientip $parsedsession$requestnumber] continent] append requestentry "Client IP Country: " append requestentry [whereis [table lookup -subtable clientip $parsedsession$requestnumber] country] append requestentry "Client IP State: " append requestentry [whereis [table lookup -subtable clientip $parsedsession$requestnumber] state] append requestentry "Response Start Delay: " append requestentry [table lookup -subtable responsestartdelay $parsedsession$requestnumber] if {$responsepayload eq ""} { } else { append requestentry "Response Finish Delay: " append requestentry [table lookup -subtable responsercvdelay $parsedsession$requestnumber] } append requestentry "" ##Output HTTP request information here append requestentry [table lookup -subtable clientmethod $parsedsession$requestnumber] append requestentry " " append requestentry [table lookup -subtable clienturi $parsedsession$requestnumber] append requestentry " HTTP/" append requestentry [table lookup -subtable clienthttpver $parsedsession$requestnumber] append requestentry "" foreach header [table lookup -subtable requestheadernames $parsedsession$requestnumber] { append requestentry $header append requestentry ": " append requestentry [table lookup -subtable requestheader$header $parsedsession$requestnumber] append requestentry "" } append requestentry "" ##Output Request Sent to Server (post-modification) here append requestentry [table lookup -subtable requestmethodsent $parsedsession$requestnumber] append requestentry " " append requestentry [table lookup -subtable requesturisent $parsedsession$requestnumber] append requestentry " HTTP/" append requestentry [table lookup -subtable requesthttpversent $parsedsession$requestnumber] append requestentry "" foreach header [table lookup -subtable requestheadernamessent $parsedsession$requestnumber] { append requestentry $header append requestentry ": " append requestentry [table lookup -subtable requestheadersent$header $parsedsession$requestnumber] append requestentry "" } append requestentry "" ##Response Output Code append requestentry "Response Status:" append requestentry [table lookup -subtable responsestatus $parsedsession$requestnumber] append requestentry "" append requestentry "Response Headers:" foreach header [table lookup -subtable responseheadernames $parsedsession$requestnumber] { append requestentry $header append requestentry ": " append requestentry [table lookup -subtable responseheader$header $parsedsession$requestnumber] append requestentry "" } append requestentry "
Published Mar 18, 2015
Version 1.0
No CommentsBe the first to comment
"}},"component({\"componentId\":\"custom.widget.Beta_MetaNav\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[\"board:codeshare\",\"message:280534\"],\"name\":\"TkbMessagePage\",\"props\":{},\"url\":\"https://community.f5.com\"}}})":{"__typename":"ComponentRenderResult","html":" "}},"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/QueryHandler\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageView/MessageViewStandard\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageView/MessageViewStandard-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/ThreadedReplyList\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/ThreadedReplyList-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageReplyCallToAction\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageReplyCallToAction-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageSubject\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageSubject-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageBody\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageBody-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageCustomFields\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageCustomFields-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageRevision\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageRevision-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageReplyButton\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageReplyButton-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageAuthorBio\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageAuthorBio-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/guides/GuideBottomNavigation\"]})":[{"__ref":"CachedAsset:text:en_US-components/guides/GuideBottomNavigation-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserLink\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserLink-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserRank\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserRank-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserRegistrationDate\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserRegistrationDate-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"components/tags/TagView/TagViewChip\"]})":[{"__ref":"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1728320186000"}],"cachedText({\"lastModified\":\"1728320186000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/ranks/UserRankLabel\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1728320186000"}]},"CachedAsset:pages-1737018051314":{"__typename":"CachedAsset","id":"pages-1737018051314","value":[{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1737018051314,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"}],"localOverride":false},"CachedAsset:text:en_US-components/context/AppContext/AppContextProvider-0":{"__typename":"CachedAsset","id":"text:en_US-components/context/AppContext/AppContextProvider-0","value":{"noCommunity":"Cannot find community","noUser":"Cannot find current user","noNode":"Cannot find node with id {nodeId}","noMessage":"Cannot find message with id {messageId}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-0":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-0","value":{"title":"Loading..."},"localOverride":false},"User:user:-1":{"__typename":"User","id":"user:-1","uid":-1,"login":"Former Member","email":"","avatar":null,"rank":null,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":"ANONYMOUS","registrationTime":null,"confirmEmailStatus":false,"registrationAccessLevel":"VIEW","ssoRegistrationFields":[]},"ssoId":null,"profileSettings":{"__typename":"ProfileSettings","dateDisplayStyle":{"__typename":"InheritableStringSettingWithPossibleValues","key":"layout.friendly_dates_enabled","value":"false","localValue":"true","possibleValues":["true","false"]},"dateDisplayFormat":{"__typename":"InheritableStringSetting","key":"layout.format_pattern_date","value":"dd-MMM-yyyy","localValue":"MM-dd-yyyy"},"language":{"__typename":"InheritableStringSettingWithPossibleValues","key":"profile.language","value":"en-US","localValue":"en","possibleValues":["en-US"]}},"deleted":false},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bi04Ny0xOTQ1NWk4ODNCOUNEMkFDNDZCQjI0\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bi04Ny0xOTQ1NWk4ODNCOUNEMkFDNDZCQjI0","mimeType":"image/png"},"Category:category:CrowdSRC":{"__typename":"Category","id":"category:CrowdSRC","entityType":"CATEGORY","displayId":"CrowdSRC","nodeType":"category","depth":1,"title":"CrowdSRC","shortTitle":"CrowdSRC","parent":{"__ref":"Category:category:top"},"categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:top":{"__typename":"Category","id":"category:top","displayId":"top","nodeType":"category","depth":0,"title":"Top","entityType":"CATEGORY","shortTitle":"Top"},"Tkb:board:codeshare":{"__typename":"Tkb","id":"board:codeshare","entityType":"TKB","displayId":"codeshare","nodeType":"board","depth":2,"conversationStyle":"TKB","title":"CodeShare","description":"Have some code. Share some code.","avatar":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bi04Ny0xOTQ1NWk4ODNCOUNEMkFDNDZCQjI0\"}"},"profileSettings":{"__typename":"ProfileSettings","language":null},"parent":{"__ref":"Category:category:CrowdSRC"},"ancestors":{"__typename":"CoreNodeConnection","edges":[{"__typename":"CoreNodeEdge","node":{"__ref":"Community:community:zihoc95639"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:CrowdSRC"}}]},"userContext":{"__typename":"NodeUserContext","canAddAttachments":false,"canUpdateNode":false,"canPostMessages":false,"isSubscribed":false},"boardPolicies":{"__typename":"BoardPolicies","canPublishArticleOnCreate":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","args":[]}},"canReadNode":{"__typename":"PolicyResult","failureReason":null}},"shortTitle":"CodeShare","isManualSortOrderAvailable":false,"tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"repliesProperties":{"__typename":"RepliesProperties","sortOrder":"PUBLISH_TIME","repliesFormat":"threaded"},"tagProperties":{"__typename":"TagNodeProperties","tagsEnabled":{"__typename":"PolicyResult","failureReason":null}},"requireTags":true,"tagType":"FREEFORM_AND_PRESET"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/cmstNDEtSzFzVEth\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/cmstNDEtSzFzVEth","height":0,"width":0,"mimeType":"image/svg+xml"},"Rank:rank:41":{"__typename":"Rank","id":"rank:41","position":18,"name":"Nimbostratus","color":"CCCCCC","icon":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/cmstNDEtSzFzVEth\"}"},"rankStyle":"FILLED"},"User:user:55636":{"__typename":"User","id":"user:55636","uid":55636,"login":"Chad_Jenison","deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-4.svg"},"rank":{"__ref":"Rank:rank:41"},"email":"","messagesCount":44,"biography":null,"topicsCount":20,"kudosReceivedCount":0,"kudosGivenCount":0,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":null,"registrationTime":"2008-05-13T01:00:00.000-07:00","confirmEmailStatus":null},"followersCount":null,"solutionsCount":0},"TkbTopicMessage:message:280534":{"__typename":"TkbTopicMessage","uid":280534,"subject":"HTTP Session Watcher","id":"message:280534","revisionNum":1,"repliesCount":0,"author":{"__ref":"User:user:55636"},"depth":0,"hasGivenKudo":false,"helpful":null,"board":{"__ref":"Tkb:board:codeshare"},"conversation":{"__ref":"Conversation:conversation:280534"},"messagePolicies":{"__typename":"MessagePolicies","canPublishArticleOnEdit":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","args":[]}},"canModerateSpamMessage":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","key":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","args":[]}}},"contentWorkflow":{"__typename":"ContentWorkflow","state":"PUBLISH","scheduledPublishTime":null,"scheduledTimezone":null,"userContext":{"__typename":"MessageWorkflowContext","canSubmitForReview":null,"canEdit":false,"canRecall":null,"canSubmitForPublication":null,"canReturnToAuthor":null,"canPublish":null,"canReturnToReview":null,"canSchedule":null},"shortScheduledTimezone":null},"readOnly":false,"editFrozen":false,"moderationData":{"__ref":"ModerationData:moderation_data:280534"},"teaser":"","body":"

Problem this snippet solves:

iRule to capture and display HTTP request and response headers (and optionally request payload) for HTTP sessions flowing through the BIG-IP

How to use this snippet:

Screenshots

\n

Code :

### HTTP Session Watcher\n### Chad Jenison - c.jenison -at- f5.com \n### version 1.0\n### A tool to record and show HTTP Sessions and their underlying requests and response headers (and response payload) on a BIG-IP\n### Notes: \n### This rule utilizes a non-trivial amount of table memory and does a pretty good amount of data-plane processing for saving traffic flow data.\n### For that reason, you probably want to be careful about deploying it on production virtual servers and begin with your same app/pool on a test virtual server with this iRule enabled\n### If you decide to migrate this to a production virtual server, you probably want to take advantage of the options available in RULE_INIT for limiting the traffic the rule captures\n### This was tested on BIG-IP 10.2\n### The most reliable codepath is to let the rule use its own cookie; use of an external (app) cookie is intended to not impact traffic and reveal use of the tool \n### BIG-IP Generated Redirects are not captured; but do not cause application misbehavior\n### Use of the rule on both an HTTP and HTTPS virtual server for the same session has not been tested and likely doesn't work yet. Will fix later.\n### Not yet tested with BIG-IP ASM,WA,APM enabled on virtual server\n### Textual HTTP Response Status is not displayed; in spite of its presence in the HTTP response. Couldn't find iRule API to access this; only numeric response status\n### To-Do: \n### Support combined HTTP&HTTPS access to the same app with session visibility provided in a protocol independent manner\n### Clean-Up table display using stylesheets\n### Add cr-lf's to raw HTTP request display\n### Support HTTP Request Payload Capture\n### Escape HTTP Response Payload for display\n\nwhen RULE_INIT {\n# If you want to use existing application session cookie as basis for tracking provide cookie name here\n  set static::externalcookiename \"JSESSIONID\"\n# By default this rule uses its own cookie; change this to 1 if using external cookie above\n  set static::useexternalcookie 0\n# Cookie Name if inserting rule-specific tracking cookie\n  set static::trackingcookie \"BIGIPHTTPWATCHER\"\n# If you want to enable IP-based restrictions on session capture, set this static variable to 1\n  set static::enablesourceipfilter 0\n# NOTE Provide enabled source IP networks in iRule datagroup named \"enablednetworks\"\n# Also, we can capture based on presence of an HTTP request header; set this variable to 1 to enable this restriction\n  set static::enablecaptureonheaderpresent 0\n  set static::magiccaptureheader \"x-bigipsession-capture\"\n# Also, we can capture based on substring match in User-Agent string; uncomment to enable this restriction\n#  set static::useragentmagicstring \"bigipsession-capture\"\n#  set static::useragentmagicstring \"Chrome\"\n# This iRule consumes a lot of processing resources as well as table memory. HTTP response payload is likely the biggest consumer of memory; to disable, set this variable to 1\n  set static::disableresponsepayloadcapture 1\n# With respect to the memory utilization problem, it also makes sense to set a shorter timeout on the response payload table entries; defaulting to 120 seconds\n  set static::responsepayloadtabletimeout 120\n## tableentrytimeout in seconds (3600 is one hour)\n  set static::tabletimeout 3600\n  set static::responsedatalimit 1048576\n  if {$static::useexternalcookie} {\n    set static::sessioncookie $static::externalcookiename\n  } else {\n    set static::sessioncookie $static::trackingcookie\n  }\n  set static::enablemagicurlviewing 1\n  set static::magicurlprefix \"/f5/bigiphttpwatcher\"\n  set static::htmlstart \"BIG-IP HTTP Session Watcher\"\n  set static::htmlend \"\"\n}\n\n\n\nwhen CLIENT_ACCEPTED {\n  set disablecapture 0\n  if {$static::enablesourceipfilter} {\n    if {[matchclass [IP::client_addr] equals $::enablednetworks]} {\n      #log local0. \"Client IP filtering enabled and Client IP matched\"\n    } else {\n      #log local0. \"Client IP filtering enabled and Client IP did not match\"\n      set disablecapture 1\n    }\n  }\n}\n\n# this code implements the session browsing UI and is given a priority of 501 because it doesn't need special early access to the HTTP Request\n# performance optimization is not a focus for this code, given that it's just powering the UI\nwhen HTTP_REQUEST priority 501 {\n  if {$static::enablemagicurlviewing} {\n    if {[HTTP::uri] starts_with $static::magicurlprefix} {\n      set magicrequest 1\n      log local0. \"BIG-IP HTTP Watcher UI Access from [IP::client_addr]\"\n      set parsedsession [URI::query [HTTP::uri] \"session\"]\n      if {$parsedsession eq \"\"} {\n        set sessionbody {

F5 BIG-IP HTTP Watcher


SessionList


}\n foreach session [table keys -subtable requestcounter] {\n set requestcount [table lookup -subtable requestcounter $session]\n set sessionline \"\"\n append sessionbody $sessionline\n }\n append sessionbody \"
Session IDRequest CountUser Agent (most recent)Source IP(most recent)
\"\n append sessionline $session\n append sessionline \"\"\n append sessionline $requestcount\n append sessionline \"\"\n append sessionline [table lookup -subtable requestheaderUser-Agent $session$last]\n append sessionline \"\"\n append sessionline [table lookup -subtable clientip $session$last]\n append sessionline \"
\"\n set htmlresponse $static::htmlstart$sessionbody$static::htmlend\n } else {\n set rawrequest [URI::query [HTTP::uri] \"rawrequest\"]\n set rawrequestsent [URI::query [HTTP::uri] \"rawrequestsent\"]\n set payload [URI::query [HTTP::uri] \"payload\"]\n set parsedrequestnumber [URI::query [HTTP::uri] \"requestnumber\"]\n if {$rawrequest eq 1} {\n set responsebody [table lookup -subtable rawrequest $parsedsession$parsedrequestnumber]\n set htmlresponse $static::htmlstart$responsebody$static::htmlend\n } elseif {$payload eq 1} {\n set htmlresponse [table lookup -subtable responsepayload $parsedsession$parsedrequestnumber]\n } else {\n ##we got a session param in the URL, so render requests from the table\n set requestbody {}\n ## this for loop will iterate over each request associated with the session, outputting a table row for each request\n for {set requestnumber 1} {$requestnumber <= [table lookup -subtable requestcounter $parsedsession]} {incr requestnumber} {\n set requestentry \"\"\n append requestbody $requestentry\n }\n set htmlresponse $static::htmlstart$requestbody$static::htmlend\n }\n }\n HTTP::respond 200 content $htmlresponse Cache-Control No-Cache Pragma No-Cache\n } \n }\n}\n\nwhen HTTP_REQUEST priority 1 {\n ## this block of code does all the work of saving HTTP request data to the table structure\n set magicrequest 0\n if {[HTTP::uri] starts_with $static::magicurlprefix} {\n set magicrequest 1\n }\n if {!$magicrequest} {\n ## here we're going to decide whether we should cature request to table\n # we're going to detect a $disablecapture variable and if it's already been set (for example based on the user's client IP not matching allowed networks) don't even bother further evaluation of restrictions\n if {!$disablecapture} {\n if {$static::enablecaptureonheaderpresent} {\n if {[HTTP::header exists $static::magiccaptureheader]} {\n #log local0. \"magic capture header required and is present\"\n } else {\n #log local0. \"magic capture header required and is missing\"\n set disablecapture 1\n }\n }\n if {[info exists static::useragentmagicstring]} {\n if {[HTTP::header User-Agent] contains $static::useragentmagicstring} {\n #log local0. \"User-Agent magic string required and present; will capture this request\"\n } else {\n #log local0. \"User-Agent magic string required and not present; disabling capture\"\n set disablecapture 1\n }\n }\n }\n if {!$disablecapture} {\n ##code to do transaction logging is here\n set nocookie 1\n if {[HTTP::cookie exists $static::sessioncookie]} {\n set nocookie 0\n set sessionid [HTTP::cookie $static::sessioncookie]\n } else {\n #This code is generating a session cookie value - found on devcentral post by Robert Sutcliffe\n set rnum [format \"%08X\" [expr { int(1000000000 * rand() ) } ] ] \n set cthash [format \"%08X\" [clock clicks -milliseconds] ] \n set sessionid \"$cthash$rnum\" \n }\n set requestnumber [table incr -subtable requestcounter -mustexist $sessionid]\n if {$requestnumber eq \"\"} {\n table set -subtable requestcounter $sessionid 1 $static::tabletimeout\n set requestnumber 1\n }\n #Here is where we store request attributes to table for later viewing\n table set -subtable rawrequest $sessionid$requestnumber [HTTP::request] $static::tabletimeout\n table set -subtable clienturi $sessionid$requestnumber [HTTP::uri] $static::tabletimeout\n table set -subtable clientmethod $sessionid$requestnumber [HTTP::method] $static::tabletimeout\n table set -subtable clienthttpver $sessionid$requestnumber [HTTP::version] $static::tabletimeout\n table set -subtable clientrequests $sessionid$requestnumber [HTTP::request] $static::tabletimeout\n table set -subtable httpreqnum $sessionid$requestnumber [HTTP::request_num] $static::tabletimeout\n table set -subtable requestheadernames $sessionid$requestnumber [HTTP::header names] $static::tabletimeout\n foreach header [HTTP::header names] {\n table set -subtable requestheader$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout\n }\n table set -subtable clientip $sessionid$requestnumber [IP::client_addr] $static::tabletimeout\n table set -subtable clientport $sessionid$requestnumber [TCP::client_port] $static::tabletimeout\n table set -subtable vsip $sessionid$requestnumber [IP::local_addr] $static::tabletimeout\n table set -subtable vsport $sessionid$requestnumber [TCP::local_port clientside] $static::tabletimeout\n table set -subtable vsname $sessionid$requestnumber [virtual] $static::tabletimeout\n table set -subtable cmpunit $sessionid$requestnumber [TMM::cmp_unit] $static::tabletimeout\n }\n }\n}\n\nwhen HTTP_REQUEST_SEND priority 501 {\n #log local0. \"disablecapture: $disablecapture\"\n if {!$disablecapture && !$magicrequest} {\n clientside {\n table set -subtable requesturisent $sessionid$requestnumber [HTTP::uri] $static::tabletimeout\n table set -subtable requestheadernamessent $sessionid$requestnumber [HTTP::header names] $static::tabletimeout\n table set -subtable requestmethodsent $sessionid$requestnumber [HTTP::method] $static::tabletimeout\n table set -subtable requesthttpversent $sessionid$requestnumber [HTTP::version] $static::tabletimeout\n foreach header [HTTP::header names] {\n table set -subtable requestheadersent$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout\n }\n }\n# table set -subtable sentrawrequest $sessionid$requestnumber [HTTP::request] $static::tabletimeout\n set requestsendtime [clock clicks -milliseconds]\n }\n}\n\nwhen HTTP_RESPONSE priority 1 {\n set dontcaptureresponse 0\n set deleterequestentries 0\n if {!$disablecapture} {\n set responsestarttime [clock clicks -milliseconds]\n # Trigger collection for up to configured limit of response data\n if {!$static::disableresponsepayloadcapture} {\n if {[HTTP::header exists \"Content-Length\"] && [HTTP::header \"Content-Length\"] <= $static::responsedatalimit}{\n set content_length [HTTP::header \"Content-Length\"]\n } else {\n set content_length $static::responsedatalimit\n }\n # Check if $content_length has been set and is not set to 0\n if { [info exists content_length] && $content_length > 0} {\n HTTP::collect $content_length\n }\n }\n # we have a serious of if/elseif/else here to deal with the possibilities regarding session cookie usage\n # *** this scenario below is when the rule itself is going to set a cookie because the request doesn't contain one\n if {$nocookie && !$static::useexternalcookie} {\n #code will insert a cookie into 1st response if we are not using external cookie and response didn't contain the cookie\n HTTP::cookie insert name $static::sessioncookie value $sessionid\n } elseif {[HTTP::cookie exists $static::sessioncookie]} {\n # *** this scenario below is used when we detect the server setting an external session cookie\n #we're hoping to find the server issuing a set-cookie right here for the external session cookie being used\n if {$requestnumber eq 1} {\n # We're here because this is a first hit and we are seeing the server do a set-cookie\n set deleterequestentries 1\n } else {\n # We're here because the server is doing a set-cookie for the session cookie and it's not the first request\n # we want to avoid destroying the old table entries\n # and let's populate the old session's final request with the response we see here (it'll also be added to the new session's first request entry)\n table set -subtable responsestatus $sessionid$requestnumber [HTTP::status] $static::tabletimeout\n table set -subtable responseheadernames $sessionid$requestnumber [HTTP::header names] $static::tabletimeout\n table set -subtable serverip $sessionid$requestnumber [IP::server_addr] $static::tabletimeout\n table set -subtable serverport $sessionid$requestnumber [TCP::server_port] $static::tabletimeout\n table set -subtable serversideip $sessionid$requestnumber [IP::local_addr] $static::tabletimeout\n table set -subtable serversideport $sessionid$requestnumber [TCP::local_port] $static::tabletimeout\n table set -subtable httprespnum $sessionid$requestnumber [HTTP::request_num] $static::tabletimeout\n table set -subtable responsestartdelay $sessionid$requestnumber [expr {$responsestarttime - $requestsendtime}] $static::tabletimeout\n foreach header [HTTP::header names] {\n table set -subtable responseheader$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout\n }\n }\n set newrequestnumber 1\n set priorsessionid $sessionid\n set sessionid [HTTP::cookie $static::sessioncookie]\n table set -subtable requestcounter $sessionid 1 $static::tabletimeout\n # this code will migrate request table entries to use the new external session cookie value as key and then delete the table entries using the (temp) priorsessionid as key\n table set -subtable rawrequest $sessionid$newrequestnumber [table lookup -subtable rawrequest $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clienturi $sessionid$newrequestnumber [table lookup -subtable clienturi $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clientmethod $sessionid$newrequestnumber [table lookup -subtable clientmethod $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clienthttpver $sessionid$newrequestnumber [table lookup -subtable clienthttpver $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clientrequests $sessionid$newrequestnumber [table lookup -subtable clientrequests $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable httpreqnum $sessionid$newrequestnumber [table lookup -subtable httpreqnumber $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requestheadernames $sessionid$newrequestnumber [table lookup -subtable requestheadernames $priorsessionid$requestnumber] $static::tabletimeout\n foreach header [table lookup -subtable requestheadernames $priorsessionid$requestnumber] {\n table set -subtable requestheader$header $sessionid$newrequestnumber [table lookup -subtable requestheader$header $priorsessionid$requestnumber] $static::tabletimeout\n }\n table set -subtable clientip $sessionid$newrequestnumber [table lookup -subtable clientip $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clientport $sessionid$newrequestnumber [table lookup -subtable clientport $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable vsip $sessionid$newrequestnumber [table lookup -subtable vsip $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable vsport $sessionid$newrequestnumber [table lookup -subtable vsport $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable vsname $sessionid$newrequestnumber [table lookup -subtable vsname $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable cmpunit $sessionid$newrequestnumber [table lookup -subtable cmpunit $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requesturisent $sessionid$newrequestnumber [table lookup -subtable requesturisent $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requestheadernamessent $sessionid$newrequestnumber [table lookup -subtable requestheadernamessent $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requestmethodsent $sessionid$newrequestnumber [table lookup -subtable requestmethodsent $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requesthttpversent $sessionid$newrequestnumber [table lookup -subtable requesthttpversent $priorsessionid$requestnumber] $static::tabletimeout\n foreach header [table lookup -subtable requestheadernamessent $priorsessionid$requestnumber] {\n table set -subtable requestheadersent$header $sessionid$newrequestnumber [table lookup -subtable requestheadersent$header $priorsessionid$requestnumber] $static::tabletimeout\n }\n set requestnumber 1\n } elseif {$nocookie} {\n # lacking cookie in request and cookie not being set in response; we'll avoid capturing response and delete the initial request table entries\n set dontcaptureresponse 1\n set deleterequestentries 1\n set priorsessionid $sessionid\n }\n if {!$dontcaptureresponse} {\n table set -subtable responsestatus $sessionid$requestnumber [HTTP::status] $static::tabletimeout\n table set -subtable responseheadernames $sessionid$requestnumber [HTTP::header names] $static::tabletimeout\n table set -subtable serverip $sessionid$requestnumber [IP::server_addr] $static::tabletimeout\n table set -subtable serverport $sessionid$requestnumber [TCP::server_port] $static::tabletimeout\n table set -subtable serversideip $sessionid$requestnumber [IP::local_addr] $static::tabletimeout\n table set -subtable serversideport $sessionid$requestnumber [TCP::local_port] $static::tabletimeout\n table set -subtable httprespnum $sessionid$requestnumber [HTTP::request_num] $static::tabletimeout\n table set -subtable responsestartdelay $sessionid$requestnumber [expr {$responsestarttime - $requestsendtime}] $static::tabletimeout\n foreach header [HTTP::header names] {\n table set -subtable responseheader$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout\n }\n }\n if {$deleterequestentries} {\n # we're deleting HTTP request table entries (and presumably the value of requestnumber is 1)\n table delete -subtable rawrequest $priorsessionid$requestnumber\n table delete -subtable clienturi $priorsessionid$requestnumber\n table delete -subtable clientmethod $priorsessionid$requestnumber\n table delete -subtable clienthttpver $priorsessionid$requestnumber\n table delete -subtable clientrequests $priorsessionid$requestnumber\n table delete -subtable httpreqnum $priorsessionid$requestnumber\n foreach header [table lookup -subtable requestheadernames $priorsessionid$requestnumber] {\n table delete -subtable requestheader$header $priorsessionid$requestnumber\n }\n table delete -subtable requestheadernames $priorsessionid$requestnumber\n table delete -subtable clientip $priorsessionid$requestnumber\n table delete -subtable clientport $priorsessionid$requestnumber\n table delete -subtable vsip $priorsessionid$requestnumber\n table delete -subtable vsport $priorsessionid$requestnumber\n table delete -subtable vsname $priorsessionid$requestnumber\n table delete -subtable cmpunit $priorsessionid$requestnumber\n table delete -subtable requesturisent $priorsessionid$requestnumber\n table delete -subtable requestheadernamessent $priorsessionid$requestnumber\n table delete -subtable requestmethodsent $priorsessionid$requestnumber\n table delete -subtable requesthttpversent $priorsessionid$requestnumber\n foreach header [HTTP::header names] {\n table delete -subtable requestheadersent$header $priorsessionid$requestnumber\n }\n table delete -subtable requestcounter $priorsessionid\n }\n }\n}\n\nwhen HTTP_RESPONSE_DATA {\n if {!$disablecapture} {\n #record time\n set responsercvtime [clock clicks -milliseconds]\n #store payload to table\n table set -subtable responsepayload $sessionid$requestnumber [HTTP::payload]\n table set -subtable responsercvdelay $sessionid$requestnumber [expr {$responsercvtime - $requestsendtime}] $static::responsepayloadtabletimeout\n }\n}
Request NumberBIG-IP InfoHTTP Request(received from client)HTTP Request(sent to server)HTTP Response
\"\n append requestentry \"$requestnumber\"\n append requestentry \"Raw Request Rcvd\"\n set responsepayload [table lookup -subtable responsepayload $parsedsession$requestnumber]\n if {$responsepayload eq \"\"} {\n } else {\n append requestentry \"Response Payload\"\n }\n append requestentry \"\"\n append requestentry \"Client IP & Port: \"\n append requestentry [table lookup -subtable clientip $parsedsession$requestnumber]\n append requestentry \":\"\n append requestentry [table lookup -subtable clientport $parsedsession$requestnumber]\n append requestentry \"\"\n append requestentry \"Client IP & Port(Server-side): \"\n append requestentry [table lookup -subtable serversideip $parsedsession$requestnumber]\n append requestentry \":\"\n append requestentry [table lookup -subtable serversideport $parsedsession$requestnumber]\n append requestentry \"\"\n append requestentry \"Virtual Server IP & Port: \"\n append requestentry [table lookup -subtable vsip $parsedsession$requestnumber]\n append requestentry \":\"\n append requestentry [table lookup -subtable vsport $parsedsession$requestnumber]\n append requestentry \"\"\n append requestentry \"Server IP & Port: \"\n append requestentry [table lookup -subtable serverip $parsedsession$requestnumber]\n append requestentry \":\"\n append requestentry [table lookup -subtable serverport $parsedsession$requestnumber]\n append requestentry \"Virtual Name: \"\n append requestentry [table lookup -subtable vsname $parsedsession$requestnumber]\n append requestentry \"CMP Unit: \"\n append requestentry [table lookup -subtable cmpunit $parsedsession$requestnumber]\n append requestentry \"HTTP Req Num on Socket: \"\n append requestentry [table lookup -subtable httpreqnum $parsedsession$requestnumber]\n append requestentry \"HTTP Resp Num on Socket: \"\n append requestentry [table lookup -subtable httprespnum $parsedsession$requestnumber]\n append requestentry \"Client IP Continent: \"\n append requestentry [whereis [table lookup -subtable clientip $parsedsession$requestnumber] continent]\n append requestentry \"Client IP Country: \"\n append requestentry [whereis [table lookup -subtable clientip $parsedsession$requestnumber] country]\n append requestentry \"Client IP State: \"\n append requestentry [whereis [table lookup -subtable clientip $parsedsession$requestnumber] state]\n append requestentry \"Response Start Delay: \"\n append requestentry [table lookup -subtable responsestartdelay $parsedsession$requestnumber]\n if {$responsepayload eq \"\"} {\n } else {\n append requestentry \"Response Finish Delay: \"\n append requestentry [table lookup -subtable responsercvdelay $parsedsession$requestnumber]\n }\n append requestentry \"\"\n ##Output HTTP request information here\n append requestentry [table lookup -subtable clientmethod $parsedsession$requestnumber]\n append requestentry \" \"\n append requestentry [table lookup -subtable clienturi $parsedsession$requestnumber]\n append requestentry \" HTTP/\"\n append requestentry [table lookup -subtable clienthttpver $parsedsession$requestnumber]\n append requestentry \"\"\n foreach header [table lookup -subtable requestheadernames $parsedsession$requestnumber] {\n append requestentry $header\n append requestentry \": \"\n append requestentry [table lookup -subtable requestheader$header $parsedsession$requestnumber]\n append requestentry \"\"\n }\n append requestentry \"\"\n ##Output Request Sent to Server (post-modification) here\n append requestentry [table lookup -subtable requestmethodsent $parsedsession$requestnumber]\n append requestentry \" \"\n append requestentry [table lookup -subtable requesturisent $parsedsession$requestnumber]\n append requestentry \" HTTP/\"\n append requestentry [table lookup -subtable requesthttpversent $parsedsession$requestnumber]\n append requestentry \"\"\n foreach header [table lookup -subtable requestheadernamessent $parsedsession$requestnumber] {\n append requestentry $header\n append requestentry \": \"\n append requestentry [table lookup -subtable requestheadersent$header $parsedsession$requestnumber]\n append requestentry \"\"\n }\n append requestentry \"\"\n ##Response Output Code\n append requestentry \"Response Status:\"\n append requestentry [table lookup -subtable responsestatus $parsedsession$requestnumber]\n append requestentry \"\"\n append requestentry \"Response Headers:\"\n foreach header [table lookup -subtable responseheadernames $parsedsession$requestnumber] {\n append requestentry $header\n append requestentry \": \"\n append requestentry [table lookup -subtable responseheader$header $parsedsession$requestnumber]\n append requestentry \"\"\n }\n append requestentry \"
","body@stringLength":"28486","rawBody":"

Problem this snippet solves:

iRule to capture and display HTTP request and response headers (and optionally request payload) for HTTP sessions flowing through the BIG-IP

How to use this snippet:

Screenshots

\n

Code :

### HTTP Session Watcher\n### Chad Jenison - c.jenison -at- f5.com \n### version 1.0\n### A tool to record and show HTTP Sessions and their underlying requests and response headers (and response payload) on a BIG-IP\n### Notes: \n### This rule utilizes a non-trivial amount of table memory and does a pretty good amount of data-plane processing for saving traffic flow data.\n### For that reason, you probably want to be careful about deploying it on production virtual servers and begin with your same app/pool on a test virtual server with this iRule enabled\n### If you decide to migrate this to a production virtual server, you probably want to take advantage of the options available in RULE_INIT for limiting the traffic the rule captures\n### This was tested on BIG-IP 10.2\n### The most reliable codepath is to let the rule use its own cookie; use of an external (app) cookie is intended to not impact traffic and reveal use of the tool \n### BIG-IP Generated Redirects are not captured; but do not cause application misbehavior\n### Use of the rule on both an HTTP and HTTPS virtual server for the same session has not been tested and likely doesn't work yet. Will fix later.\n### Not yet tested with BIG-IP ASM,WA,APM enabled on virtual server\n### Textual HTTP Response Status is not displayed; in spite of its presence in the HTTP response. Couldn't find iRule API to access this; only numeric response status\n### To-Do: \n### Support combined HTTP&HTTPS access to the same app with session visibility provided in a protocol independent manner\n### Clean-Up table display using stylesheets\n### Add cr-lf's to raw HTTP request display\n### Support HTTP Request Payload Capture\n### Escape HTTP Response Payload for display\n\nwhen RULE_INIT {\n# If you want to use existing application session cookie as basis for tracking provide cookie name here\n  set static::externalcookiename \"JSESSIONID\"\n# By default this rule uses its own cookie; change this to 1 if using external cookie above\n  set static::useexternalcookie 0\n# Cookie Name if inserting rule-specific tracking cookie\n  set static::trackingcookie \"BIGIPHTTPWATCHER\"\n# If you want to enable IP-based restrictions on session capture, set this static variable to 1\n  set static::enablesourceipfilter 0\n# NOTE Provide enabled source IP networks in iRule datagroup named \"enablednetworks\"\n# Also, we can capture based on presence of an HTTP request header; set this variable to 1 to enable this restriction\n  set static::enablecaptureonheaderpresent 0\n  set static::magiccaptureheader \"x-bigipsession-capture\"\n# Also, we can capture based on substring match in User-Agent string; uncomment to enable this restriction\n#  set static::useragentmagicstring \"bigipsession-capture\"\n#  set static::useragentmagicstring \"Chrome\"\n# This iRule consumes a lot of processing resources as well as table memory. HTTP response payload is likely the biggest consumer of memory; to disable, set this variable to 1\n  set static::disableresponsepayloadcapture 1\n# With respect to the memory utilization problem, it also makes sense to set a shorter timeout on the response payload table entries; defaulting to 120 seconds\n  set static::responsepayloadtabletimeout 120\n## tableentrytimeout in seconds (3600 is one hour)\n  set static::tabletimeout 3600\n  set static::responsedatalimit 1048576\n  if {$static::useexternalcookie} {\n    set static::sessioncookie $static::externalcookiename\n  } else {\n    set static::sessioncookie $static::trackingcookie\n  }\n  set static::enablemagicurlviewing 1\n  set static::magicurlprefix \"/f5/bigiphttpwatcher\"\n  set static::htmlstart \"BIG-IP HTTP Session Watcher\"\n  set static::htmlend \"\"\n}\n\n\n\nwhen CLIENT_ACCEPTED {\n  set disablecapture 0\n  if {$static::enablesourceipfilter} {\n    if {[matchclass [IP::client_addr] equals $::enablednetworks]} {\n      #log local0. \"Client IP filtering enabled and Client IP matched\"\n    } else {\n      #log local0. \"Client IP filtering enabled and Client IP did not match\"\n      set disablecapture 1\n    }\n  }\n}\n\n# this code implements the session browsing UI and is given a priority of 501 because it doesn't need special early access to the HTTP Request\n# performance optimization is not a focus for this code, given that it's just powering the UI\nwhen HTTP_REQUEST priority 501 {\n  if {$static::enablemagicurlviewing} {\n    if {[HTTP::uri] starts_with $static::magicurlprefix} {\n      set magicrequest 1\n      log local0. \"BIG-IP HTTP Watcher UI Access from [IP::client_addr]\"\n      set parsedsession [URI::query [HTTP::uri] \"session\"]\n      if {$parsedsession eq \"\"} {\n        set sessionbody {

F5 BIG-IP HTTP Watcher


SessionList


}\n foreach session [table keys -subtable requestcounter] {\n set requestcount [table lookup -subtable requestcounter $session]\n set sessionline \"\"\n append sessionbody $sessionline\n }\n append sessionbody \"
Session IDRequest CountUser Agent (most recent)Source IP(most recent)
\"\n append sessionline $session\n append sessionline \"\"\n append sessionline $requestcount\n append sessionline \"\"\n append sessionline [table lookup -subtable requestheaderUser-Agent $session$last]\n append sessionline \"\"\n append sessionline [table lookup -subtable clientip $session$last]\n append sessionline \"
\"\n set htmlresponse $static::htmlstart$sessionbody$static::htmlend\n } else {\n set rawrequest [URI::query [HTTP::uri] \"rawrequest\"]\n set rawrequestsent [URI::query [HTTP::uri] \"rawrequestsent\"]\n set payload [URI::query [HTTP::uri] \"payload\"]\n set parsedrequestnumber [URI::query [HTTP::uri] \"requestnumber\"]\n if {$rawrequest eq 1} {\n set responsebody [table lookup -subtable rawrequest $parsedsession$parsedrequestnumber]\n set htmlresponse $static::htmlstart$responsebody$static::htmlend\n } elseif {$payload eq 1} {\n set htmlresponse [table lookup -subtable responsepayload $parsedsession$parsedrequestnumber]\n } else {\n ##we got a session param in the URL, so render requests from the table\n set requestbody {}\n ## this for loop will iterate over each request associated with the session, outputting a table row for each request\n for {set requestnumber 1} {$requestnumber <= [table lookup -subtable requestcounter $parsedsession]} {incr requestnumber} {\n set requestentry \"\"\n append requestbody $requestentry\n }\n set htmlresponse $static::htmlstart$requestbody$static::htmlend\n }\n }\n HTTP::respond 200 content $htmlresponse Cache-Control No-Cache Pragma No-Cache\n } \n }\n}\n\nwhen HTTP_REQUEST priority 1 {\n ## this block of code does all the work of saving HTTP request data to the table structure\n set magicrequest 0\n if {[HTTP::uri] starts_with $static::magicurlprefix} {\n set magicrequest 1\n }\n if {!$magicrequest} {\n ## here we're going to decide whether we should cature request to table\n # we're going to detect a $disablecapture variable and if it's already been set (for example based on the user's client IP not matching allowed networks) don't even bother further evaluation of restrictions\n if {!$disablecapture} {\n if {$static::enablecaptureonheaderpresent} {\n if {[HTTP::header exists $static::magiccaptureheader]} {\n #log local0. \"magic capture header required and is present\"\n } else {\n #log local0. \"magic capture header required and is missing\"\n set disablecapture 1\n }\n }\n if {[info exists static::useragentmagicstring]} {\n if {[HTTP::header User-Agent] contains $static::useragentmagicstring} {\n #log local0. \"User-Agent magic string required and present; will capture this request\"\n } else {\n #log local0. \"User-Agent magic string required and not present; disabling capture\"\n set disablecapture 1\n }\n }\n }\n if {!$disablecapture} {\n ##code to do transaction logging is here\n set nocookie 1\n if {[HTTP::cookie exists $static::sessioncookie]} {\n set nocookie 0\n set sessionid [HTTP::cookie $static::sessioncookie]\n } else {\n #This code is generating a session cookie value - found on devcentral post by Robert Sutcliffe\n set rnum [format \"%08X\" [expr { int(1000000000 * rand() ) } ] ] \n set cthash [format \"%08X\" [clock clicks -milliseconds] ] \n set sessionid \"$cthash$rnum\" \n }\n set requestnumber [table incr -subtable requestcounter -mustexist $sessionid]\n if {$requestnumber eq \"\"} {\n table set -subtable requestcounter $sessionid 1 $static::tabletimeout\n set requestnumber 1\n }\n #Here is where we store request attributes to table for later viewing\n table set -subtable rawrequest $sessionid$requestnumber [HTTP::request] $static::tabletimeout\n table set -subtable clienturi $sessionid$requestnumber [HTTP::uri] $static::tabletimeout\n table set -subtable clientmethod $sessionid$requestnumber [HTTP::method] $static::tabletimeout\n table set -subtable clienthttpver $sessionid$requestnumber [HTTP::version] $static::tabletimeout\n table set -subtable clientrequests $sessionid$requestnumber [HTTP::request] $static::tabletimeout\n table set -subtable httpreqnum $sessionid$requestnumber [HTTP::request_num] $static::tabletimeout\n table set -subtable requestheadernames $sessionid$requestnumber [HTTP::header names] $static::tabletimeout\n foreach header [HTTP::header names] {\n table set -subtable requestheader$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout\n }\n table set -subtable clientip $sessionid$requestnumber [IP::client_addr] $static::tabletimeout\n table set -subtable clientport $sessionid$requestnumber [TCP::client_port] $static::tabletimeout\n table set -subtable vsip $sessionid$requestnumber [IP::local_addr] $static::tabletimeout\n table set -subtable vsport $sessionid$requestnumber [TCP::local_port clientside] $static::tabletimeout\n table set -subtable vsname $sessionid$requestnumber [virtual] $static::tabletimeout\n table set -subtable cmpunit $sessionid$requestnumber [TMM::cmp_unit] $static::tabletimeout\n }\n }\n}\n\nwhen HTTP_REQUEST_SEND priority 501 {\n #log local0. \"disablecapture: $disablecapture\"\n if {!$disablecapture && !$magicrequest} {\n clientside {\n table set -subtable requesturisent $sessionid$requestnumber [HTTP::uri] $static::tabletimeout\n table set -subtable requestheadernamessent $sessionid$requestnumber [HTTP::header names] $static::tabletimeout\n table set -subtable requestmethodsent $sessionid$requestnumber [HTTP::method] $static::tabletimeout\n table set -subtable requesthttpversent $sessionid$requestnumber [HTTP::version] $static::tabletimeout\n foreach header [HTTP::header names] {\n table set -subtable requestheadersent$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout\n }\n }\n# table set -subtable sentrawrequest $sessionid$requestnumber [HTTP::request] $static::tabletimeout\n set requestsendtime [clock clicks -milliseconds]\n }\n}\n\nwhen HTTP_RESPONSE priority 1 {\n set dontcaptureresponse 0\n set deleterequestentries 0\n if {!$disablecapture} {\n set responsestarttime [clock clicks -milliseconds]\n # Trigger collection for up to configured limit of response data\n if {!$static::disableresponsepayloadcapture} {\n if {[HTTP::header exists \"Content-Length\"] && [HTTP::header \"Content-Length\"] <= $static::responsedatalimit}{\n set content_length [HTTP::header \"Content-Length\"]\n } else {\n set content_length $static::responsedatalimit\n }\n # Check if $content_length has been set and is not set to 0\n if { [info exists content_length] && $content_length > 0} {\n HTTP::collect $content_length\n }\n }\n # we have a serious of if/elseif/else here to deal with the possibilities regarding session cookie usage\n # *** this scenario below is when the rule itself is going to set a cookie because the request doesn't contain one\n if {$nocookie && !$static::useexternalcookie} {\n #code will insert a cookie into 1st response if we are not using external cookie and response didn't contain the cookie\n HTTP::cookie insert name $static::sessioncookie value $sessionid\n } elseif {[HTTP::cookie exists $static::sessioncookie]} {\n # *** this scenario below is used when we detect the server setting an external session cookie\n #we're hoping to find the server issuing a set-cookie right here for the external session cookie being used\n if {$requestnumber eq 1} {\n # We're here because this is a first hit and we are seeing the server do a set-cookie\n set deleterequestentries 1\n } else {\n # We're here because the server is doing a set-cookie for the session cookie and it's not the first request\n # we want to avoid destroying the old table entries\n # and let's populate the old session's final request with the response we see here (it'll also be added to the new session's first request entry)\n table set -subtable responsestatus $sessionid$requestnumber [HTTP::status] $static::tabletimeout\n table set -subtable responseheadernames $sessionid$requestnumber [HTTP::header names] $static::tabletimeout\n table set -subtable serverip $sessionid$requestnumber [IP::server_addr] $static::tabletimeout\n table set -subtable serverport $sessionid$requestnumber [TCP::server_port] $static::tabletimeout\n table set -subtable serversideip $sessionid$requestnumber [IP::local_addr] $static::tabletimeout\n table set -subtable serversideport $sessionid$requestnumber [TCP::local_port] $static::tabletimeout\n table set -subtable httprespnum $sessionid$requestnumber [HTTP::request_num] $static::tabletimeout\n table set -subtable responsestartdelay $sessionid$requestnumber [expr {$responsestarttime - $requestsendtime}] $static::tabletimeout\n foreach header [HTTP::header names] {\n table set -subtable responseheader$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout\n }\n }\n set newrequestnumber 1\n set priorsessionid $sessionid\n set sessionid [HTTP::cookie $static::sessioncookie]\n table set -subtable requestcounter $sessionid 1 $static::tabletimeout\n # this code will migrate request table entries to use the new external session cookie value as key and then delete the table entries using the (temp) priorsessionid as key\n table set -subtable rawrequest $sessionid$newrequestnumber [table lookup -subtable rawrequest $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clienturi $sessionid$newrequestnumber [table lookup -subtable clienturi $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clientmethod $sessionid$newrequestnumber [table lookup -subtable clientmethod $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clienthttpver $sessionid$newrequestnumber [table lookup -subtable clienthttpver $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clientrequests $sessionid$newrequestnumber [table lookup -subtable clientrequests $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable httpreqnum $sessionid$newrequestnumber [table lookup -subtable httpreqnumber $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requestheadernames $sessionid$newrequestnumber [table lookup -subtable requestheadernames $priorsessionid$requestnumber] $static::tabletimeout\n foreach header [table lookup -subtable requestheadernames $priorsessionid$requestnumber] {\n table set -subtable requestheader$header $sessionid$newrequestnumber [table lookup -subtable requestheader$header $priorsessionid$requestnumber] $static::tabletimeout\n }\n table set -subtable clientip $sessionid$newrequestnumber [table lookup -subtable clientip $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable clientport $sessionid$newrequestnumber [table lookup -subtable clientport $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable vsip $sessionid$newrequestnumber [table lookup -subtable vsip $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable vsport $sessionid$newrequestnumber [table lookup -subtable vsport $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable vsname $sessionid$newrequestnumber [table lookup -subtable vsname $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable cmpunit $sessionid$newrequestnumber [table lookup -subtable cmpunit $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requesturisent $sessionid$newrequestnumber [table lookup -subtable requesturisent $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requestheadernamessent $sessionid$newrequestnumber [table lookup -subtable requestheadernamessent $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requestmethodsent $sessionid$newrequestnumber [table lookup -subtable requestmethodsent $priorsessionid$requestnumber] $static::tabletimeout\n table set -subtable requesthttpversent $sessionid$newrequestnumber [table lookup -subtable requesthttpversent $priorsessionid$requestnumber] $static::tabletimeout\n foreach header [table lookup -subtable requestheadernamessent $priorsessionid$requestnumber] {\n table set -subtable requestheadersent$header $sessionid$newrequestnumber [table lookup -subtable requestheadersent$header $priorsessionid$requestnumber] $static::tabletimeout\n }\n set requestnumber 1\n } elseif {$nocookie} {\n # lacking cookie in request and cookie not being set in response; we'll avoid capturing response and delete the initial request table entries\n set dontcaptureresponse 1\n set deleterequestentries 1\n set priorsessionid $sessionid\n }\n if {!$dontcaptureresponse} {\n table set -subtable responsestatus $sessionid$requestnumber [HTTP::status] $static::tabletimeout\n table set -subtable responseheadernames $sessionid$requestnumber [HTTP::header names] $static::tabletimeout\n table set -subtable serverip $sessionid$requestnumber [IP::server_addr] $static::tabletimeout\n table set -subtable serverport $sessionid$requestnumber [TCP::server_port] $static::tabletimeout\n table set -subtable serversideip $sessionid$requestnumber [IP::local_addr] $static::tabletimeout\n table set -subtable serversideport $sessionid$requestnumber [TCP::local_port] $static::tabletimeout\n table set -subtable httprespnum $sessionid$requestnumber [HTTP::request_num] $static::tabletimeout\n table set -subtable responsestartdelay $sessionid$requestnumber [expr {$responsestarttime - $requestsendtime}] $static::tabletimeout\n foreach header [HTTP::header names] {\n table set -subtable responseheader$header $sessionid$requestnumber [HTTP::header $header] $static::tabletimeout\n }\n }\n if {$deleterequestentries} {\n # we're deleting HTTP request table entries (and presumably the value of requestnumber is 1)\n table delete -subtable rawrequest $priorsessionid$requestnumber\n table delete -subtable clienturi $priorsessionid$requestnumber\n table delete -subtable clientmethod $priorsessionid$requestnumber\n table delete -subtable clienthttpver $priorsessionid$requestnumber\n table delete -subtable clientrequests $priorsessionid$requestnumber\n table delete -subtable httpreqnum $priorsessionid$requestnumber\n foreach header [table lookup -subtable requestheadernames $priorsessionid$requestnumber] {\n table delete -subtable requestheader$header $priorsessionid$requestnumber\n }\n table delete -subtable requestheadernames $priorsessionid$requestnumber\n table delete -subtable clientip $priorsessionid$requestnumber\n table delete -subtable clientport $priorsessionid$requestnumber\n table delete -subtable vsip $priorsessionid$requestnumber\n table delete -subtable vsport $priorsessionid$requestnumber\n table delete -subtable vsname $priorsessionid$requestnumber\n table delete -subtable cmpunit $priorsessionid$requestnumber\n table delete -subtable requesturisent $priorsessionid$requestnumber\n table delete -subtable requestheadernamessent $priorsessionid$requestnumber\n table delete -subtable requestmethodsent $priorsessionid$requestnumber\n table delete -subtable requesthttpversent $priorsessionid$requestnumber\n foreach header [HTTP::header names] {\n table delete -subtable requestheadersent$header $priorsessionid$requestnumber\n }\n table delete -subtable requestcounter $priorsessionid\n }\n }\n}\n\nwhen HTTP_RESPONSE_DATA {\n if {!$disablecapture} {\n #record time\n set responsercvtime [clock clicks -milliseconds]\n #store payload to table\n table set -subtable responsepayload $sessionid$requestnumber [HTTP::payload]\n table set -subtable responsercvdelay $sessionid$requestnumber [expr {$responsercvtime - $requestsendtime}] $static::responsepayloadtabletimeout\n }\n}
Request NumberBIG-IP InfoHTTP Request(received from client)HTTP Request(sent to server)HTTP Response
\"\n append requestentry \"$requestnumber\"\n append requestentry \"Raw Request Rcvd\"\n set responsepayload [table lookup -subtable responsepayload $parsedsession$requestnumber]\n if {$responsepayload eq \"\"} {\n } else {\n append requestentry \"Response Payload\"\n }\n append requestentry \"\"\n append requestentry \"Client IP & Port: \"\n append requestentry [table lookup -subtable clientip $parsedsession$requestnumber]\n append requestentry \":\"\n append requestentry [table lookup -subtable clientport $parsedsession$requestnumber]\n append requestentry \"\"\n append requestentry \"Client IP & Port(Server-side): \"\n append requestentry [table lookup -subtable serversideip $parsedsession$requestnumber]\n append requestentry \":\"\n append requestentry [table lookup -subtable serversideport $parsedsession$requestnumber]\n append requestentry \"\"\n append requestentry \"Virtual Server IP & Port: \"\n append requestentry [table lookup -subtable vsip $parsedsession$requestnumber]\n append requestentry \":\"\n append requestentry [table lookup -subtable vsport $parsedsession$requestnumber]\n append requestentry \"\"\n append requestentry \"Server IP & Port: \"\n append requestentry [table lookup -subtable serverip $parsedsession$requestnumber]\n append requestentry \":\"\n append requestentry [table lookup -subtable serverport $parsedsession$requestnumber]\n append requestentry \"Virtual Name: \"\n append requestentry [table lookup -subtable vsname $parsedsession$requestnumber]\n append requestentry \"CMP Unit: \"\n append requestentry [table lookup -subtable cmpunit $parsedsession$requestnumber]\n append requestentry \"HTTP Req Num on Socket: \"\n append requestentry [table lookup -subtable httpreqnum $parsedsession$requestnumber]\n append requestentry \"HTTP Resp Num on Socket: \"\n append requestentry [table lookup -subtable httprespnum $parsedsession$requestnumber]\n append requestentry \"Client IP Continent: \"\n append requestentry [whereis [table lookup -subtable clientip $parsedsession$requestnumber] continent]\n append requestentry \"Client IP Country: \"\n append requestentry [whereis [table lookup -subtable clientip $parsedsession$requestnumber] country]\n append requestentry \"Client IP State: \"\n append requestentry [whereis [table lookup -subtable clientip $parsedsession$requestnumber] state]\n append requestentry \"Response Start Delay: \"\n append requestentry [table lookup -subtable responsestartdelay $parsedsession$requestnumber]\n if {$responsepayload eq \"\"} {\n } else {\n append requestentry \"Response Finish Delay: \"\n append requestentry [table lookup -subtable responsercvdelay $parsedsession$requestnumber]\n }\n append requestentry \"\"\n ##Output HTTP request information here\n append requestentry [table lookup -subtable clientmethod $parsedsession$requestnumber]\n append requestentry \" \"\n append requestentry [table lookup -subtable clienturi $parsedsession$requestnumber]\n append requestentry \" HTTP/\"\n append requestentry [table lookup -subtable clienthttpver $parsedsession$requestnumber]\n append requestentry \"\"\n foreach header [table lookup -subtable requestheadernames $parsedsession$requestnumber] {\n append requestentry $header\n append requestentry \": \"\n append requestentry [table lookup -subtable requestheader$header $parsedsession$requestnumber]\n append requestentry \"\"\n }\n append requestentry \"\"\n ##Output Request Sent to Server (post-modification) here\n append requestentry [table lookup -subtable requestmethodsent $parsedsession$requestnumber]\n append requestentry \" \"\n append requestentry [table lookup -subtable requesturisent $parsedsession$requestnumber]\n append requestentry \" HTTP/\"\n append requestentry [table lookup -subtable requesthttpversent $parsedsession$requestnumber]\n append requestentry \"\"\n foreach header [table lookup -subtable requestheadernamessent $parsedsession$requestnumber] {\n append requestentry $header\n append requestentry \": \"\n append requestentry [table lookup -subtable requestheadersent$header $parsedsession$requestnumber]\n append requestentry \"\"\n }\n append requestentry \"\"\n ##Response Output Code\n append requestentry \"Response Status:\"\n append requestentry [table lookup -subtable responsestatus $parsedsession$requestnumber]\n append requestentry \"\"\n append requestentry \"Response Headers:\"\n foreach header [table lookup -subtable responseheadernames $parsedsession$requestnumber] {\n append requestentry $header\n append requestentry \": \"\n append requestentry [table lookup -subtable responseheader$header $parsedsession$requestnumber]\n append requestentry \"\"\n }\n append requestentry \"
","kudosSumWeight":0,"postTime":"2015-03-18T11:46:09.000-07:00","images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"attachments":{"__typename":"AttachmentConnection","pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null},"edges":[]},"tags":{"__typename":"TagConnection","pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null},"edges":[{"__typename":"TagEdge","cursor":"MjQuMTF8Mi4xfG98MTB8X05WX3wx","node":{"__typename":"Tag","id":"tag:application delivery","text":"application delivery","time":"2021-06-30T01:48:44.000-07:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjQuMTF8Mi4xfG98MTB8X05WX3wy","node":{"__typename":"Tag","id":"tag:devops","text":"devops","time":"2011-10-19T17:50:55.000-07:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjQuMTF8Mi4xfG98MTB8X05WX3wz","node":{"__typename":"Tag","id":"tag:iRules","text":"iRules","time":"2022-01-24T02:29:45.106-08:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjQuMTF8Mi4xfG98MTB8X05WX3w0","node":{"__typename":"Tag","id":"tag:reporting","text":"reporting","time":"2022-01-24T02:30:25.788-08:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}}]},"timeToRead":12,"rawTeaser":"","introduction":"","currentRevision":{"__ref":"Revision:revision:280534_1"},"latestVersion":{"__typename":"FriendlyVersion","major":"1","minor":"0"},"metrics":{"__typename":"MessageMetrics","views":233},"visibilityScope":"PUBLIC","canonicalUrl":null,"seoTitle":null,"seoDescription":null,"placeholder":false,"originalMessageForPlaceholder":null,"contributors":{"__typename":"UserConnection","edges":[]},"nonCoAuthorContributors":{"__typename":"UserConnection","edges":[]},"coAuthors":{"__typename":"UserConnection","edges":[{"__typename":"UserEdge","node":{"__ref":"User:user:55636"}}]},"tkbMessagePolicies":{"__typename":"TkbMessagePolicies","canDoAuthoringActionsOnTkb":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.tkb.policy_can_do_authoring_action.accessDenied","key":"error.lithium.policies.tkb.policy_can_do_authoring_action.accessDenied","args":[]}}},"archivalData":null,"replies":{"__typename":"MessageConnection","edges":[],"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"customFields":[],"revisions({\"constraints\":{\"isPublished\":{\"eq\":true}},\"first\":1})":{"__typename":"RevisionConnection","totalCount":1}},"Conversation:conversation:280534":{"__typename":"Conversation","id":"conversation:280534","solved":false,"topic":{"__ref":"TkbTopicMessage:message:280534"},"lastPostingActivityTime":"2015-03-18T11:46:09.000-07:00","lastPostTime":"2015-03-18T11:46:09.000-07:00","unreadReplyCount":0,"isSubscribed":false},"ModerationData:moderation_data:280534":{"__typename":"ModerationData","id":"moderation_data:280534","status":"APPROVED","rejectReason":null,"isReportedAbuse":false,"rejectUser":null,"rejectTime":null,"rejectActorType":null},"Revision:revision:280534_1":{"__typename":"Revision","id":"revision:280534_1","lastEditTime":"2015-03-18T11:46:09.000-07:00"},"CachedAsset:theme:customTheme1-1737018050889":{"__typename":"CachedAsset","id":"theme:customTheme1-1737018050889","value":{"id":"customTheme1","animation":{"fast":"150ms","normal":"250ms","slow":"500ms","slowest":"750ms","function":"cubic-bezier(0.07, 0.91, 0.51, 1)","__typename":"AnimationThemeSettings"},"avatar":{"borderRadius":"50%","collections":["custom"],"__typename":"AvatarThemeSettings"},"basics":{"browserIcon":{"imageAssetName":"JimmyPackets-512-1702592938213.png","imageLastModified":"1702592945815","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"f5_logo_fix-1704824537976.svg","imageLastModified":"1704824540697","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"1600px","oneColumnNarrowWidth":"800px","gridGutterWidthMd":"30px","gridGutterWidthXs":"10px","pageWidthStyle":"WIDTH_OF_PAGE_CONTENT","__typename":"BasicsThemeSettings"},"buttons":{"borderRadiusSm":"5px","borderRadius":"5px","borderRadiusLg":"5px","paddingY":"5px","paddingYLg":"7px","paddingYHero":"var(--lia-bs-btn-padding-y-lg)","paddingX":"12px","paddingXLg":"14px","paddingXHero":"42px","fontStyle":"NORMAL","fontWeight":"400","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"var(--lia-bs-primary)","primaryBgHoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.85))","primaryBgActiveColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.7))","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","secondaryTextColor":"var(--lia-bs-gray-900)","secondaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","secondaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","secondaryBgColor":"var(--lia-bs-gray-400)","secondaryBgHoverColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.96))","secondaryBgActiveColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.92))","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","tertiaryTextColor":"var(--lia-bs-gray-900)","tertiaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","tertiaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","destructiveTextColor":"var(--lia-bs-danger)","destructiveTextHoverColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.95))","destructiveTextActiveColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.9))","destructiveBgColor":"var(--lia-bs-gray-300)","destructiveBgHoverColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.96))","destructiveBgActiveColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.92))","destructiveBorder":"1px solid transparent","destructiveBorderHover":"1px solid transparent","destructiveBorderActive":"1px solid transparent","destructiveBorderFocus":"1px solid transparent","destructiveBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","__typename":"ButtonsThemeSettings"},"border":{"color":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","mainContent":"NONE","sideContent":"NONE","radiusSm":"3px","radius":"5px","radiusLg":"9px","radius50":"100vw","__typename":"BorderThemeSettings"},"boxShadow":{"xs":"0 0 0 1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08), 0 3px 0 -1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.06)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","__typename":"BoxShadowThemeSettings"},"cards":{"bgColor":"var(--lia-panel-bg-color)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":"var(--lia-box-shadow-xs)","__typename":"CardsThemeSettings"},"chip":{"maxWidth":"300px","height":"30px","__typename":"ChipThemeSettings"},"coreTypes":{"defaultMessageLinkColor":"var(--lia-bs-primary)","defaultMessageLinkDecoration":"none","defaultMessageLinkFontStyle":"NORMAL","defaultMessageLinkFontWeight":"400","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","forumColor":"#0C5C8D","forumFontFamily":"var(--lia-bs-font-family-base)","forumFontWeight":"var(--lia-default-message-font-weight)","forumLineHeight":"var(--lia-bs-line-height-base)","forumFontStyle":"var(--lia-default-message-font-style)","forumMessageLinkColor":"var(--lia-default-message-link-color)","forumMessageLinkDecoration":"var(--lia-default-message-link-decoration)","forumMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","forumMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","forumSolvedColor":"#62C026","blogColor":"#730015","blogFontFamily":"var(--lia-bs-font-family-base)","blogFontWeight":"var(--lia-default-message-font-weight)","blogLineHeight":"1.75","blogFontStyle":"var(--lia-default-message-font-style)","blogMessageLinkColor":"var(--lia-default-message-link-color)","blogMessageLinkDecoration":"var(--lia-default-message-link-decoration)","blogMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","blogMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","tkbColor":"#C20025","tkbFontFamily":"var(--lia-bs-font-family-base)","tkbFontWeight":"var(--lia-default-message-font-weight)","tkbLineHeight":"1.75","tkbFontStyle":"var(--lia-default-message-font-style)","tkbMessageLinkColor":"var(--lia-default-message-link-color)","tkbMessageLinkDecoration":"var(--lia-default-message-link-decoration)","tkbMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","tkbMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaColor":"#4099E2","qandaFontFamily":"var(--lia-bs-font-family-base)","qandaFontWeight":"var(--lia-default-message-font-weight)","qandaLineHeight":"var(--lia-bs-line-height-base)","qandaFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkColor":"var(--lia-default-message-link-color)","qandaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","qandaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaSolvedColor":"#3FA023","ideaColor":"#F3704B","ideaFontFamily":"var(--lia-bs-font-family-base)","ideaFontWeight":"var(--lia-default-message-font-weight)","ideaLineHeight":"var(--lia-bs-line-height-base)","ideaFontStyle":"var(--lia-default-message-font-style)","ideaMessageLinkColor":"var(--lia-default-message-link-color)","ideaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","ideaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","ideaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","contestColor":"#FCC845","contestFontFamily":"var(--lia-bs-font-family-base)","contestFontWeight":"var(--lia-default-message-font-weight)","contestLineHeight":"var(--lia-bs-line-height-base)","contestFontStyle":"var(--lia-default-message-link-font-style)","contestMessageLinkColor":"var(--lia-default-message-link-color)","contestMessageLinkDecoration":"var(--lia-default-message-link-decoration)","contestMessageLinkFontStyle":"ITALIC","contestMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","occasionColor":"#EE4B5B","occasionFontFamily":"var(--lia-bs-font-family-base)","occasionFontWeight":"var(--lia-default-message-font-weight)","occasionLineHeight":"var(--lia-bs-line-height-base)","occasionFontStyle":"var(--lia-default-message-font-style)","occasionMessageLinkColor":"var(--lia-default-message-link-color)","occasionMessageLinkDecoration":"var(--lia-default-message-link-decoration)","occasionMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","occasionMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","grouphubColor":"#491B62","categoryColor":"#949494","communityColor":"#FFFFFF","productColor":"#949494","__typename":"CoreTypesThemeSettings"},"colors":{"black":"#000000","white":"#FFFFFF","gray100":"#F7F7F7","gray200":"#F7F7F7","gray300":"#E8E8E8","gray400":"#D9D9D9","gray500":"#CCCCCC","gray600":"#949494","gray700":"#707070","gray800":"#545454","gray900":"#333333","dark":"#545454","light":"#F7F7F7","primary":"#0C5C8D","secondary":"#333333","bodyText":"#222222","bodyBg":"#F5F5F5","info":"#1D9CD3","success":"#62C026","warning":"#FFD651","danger":"#C20025","alertSystem":"#FF6600","textMuted":"#707070","highlight":"#FFFCAD","outline":"var(--lia-bs-primary)","custom":["#C20025","#081B85","#009639","#B3C6D7","#7CC0EB","#F29A36"],"__typename":"ColorsThemeSettings"},"divider":{"size":"3px","marginLeft":"4px","marginRight":"4px","borderRadius":"50%","bgColor":"var(--lia-bs-gray-600)","bgColorActive":"var(--lia-bs-gray-600)","__typename":"DividerThemeSettings"},"dropdown":{"fontSize":"var(--lia-bs-font-size-sm)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius-sm)","dividerBg":"var(--lia-bs-gray-300)","itemPaddingY":"5px","itemPaddingX":"20px","headerColor":"var(--lia-bs-gray-700)","__typename":"DropdownThemeSettings"},"email":{"link":{"color":"#0069D4","hoverColor":"#0061c2","decoration":"none","hoverDecoration":"underline","__typename":"EmailLinkSettings"},"border":{"color":"#e4e4e4","__typename":"EmailBorderSettings"},"buttons":{"borderRadiusLg":"5px","paddingXLg":"16px","paddingYLg":"7px","fontWeight":"700","primaryTextColor":"#ffffff","primaryTextHoverColor":"#ffffff","primaryBgColor":"#0069D4","primaryBgHoverColor":"#005cb8","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","__typename":"EmailButtonsSettings"},"panel":{"borderRadius":"5px","borderColor":"#e4e4e4","__typename":"EmailPanelSettings"},"__typename":"EmailThemeSettings"},"emoji":{"skinToneDefault":"#ffcd43","skinToneLight":"#fae3c5","skinToneMediumLight":"#e2cfa5","skinToneMedium":"#daa478","skinToneMediumDark":"#a78058","skinToneDark":"#5e4d43","__typename":"EmojiThemeSettings"},"heading":{"color":"var(--lia-bs-body-color)","fontFamily":"Inter","fontStyle":"NORMAL","fontWeight":"600","h1FontSize":"30px","h2FontSize":"25px","h3FontSize":"20px","h4FontSize":"18px","h5FontSize":"16px","h6FontSize":"16px","lineHeight":"1.2","subHeaderFontSize":"11px","subHeaderFontWeight":"500","h1LetterSpacing":"normal","h2LetterSpacing":"normal","h3LetterSpacing":"normal","h4LetterSpacing":"normal","h5LetterSpacing":"normal","h6LetterSpacing":"normal","subHeaderLetterSpacing":"2px","h1FontWeight":null,"h2FontWeight":null,"h3FontWeight":null,"h4FontWeight":null,"h5FontWeight":null,"h6FontWeight":null,"__typename":"HeadingThemeSettings"},"icons":{"size10":"10px","size12":"12px","size14":"14px","size16":"16px","size20":"20px","size24":"24px","size30":"30px","size40":"40px","size50":"50px","size60":"60px","size80":"80px","size120":"120px","size160":"160px","__typename":"IconsThemeSettings"},"imagePreview":{"bgColor":"var(--lia-bs-gray-900)","titleColor":"var(--lia-bs-white)","controlColor":"var(--lia-bs-white)","controlBgColor":"var(--lia-bs-gray-800)","__typename":"ImagePreviewThemeSettings"},"input":{"borderColor":"var(--lia-bs-gray-600)","disabledColor":"var(--lia-bs-gray-600)","focusBorderColor":"var(--lia-bs-primary)","labelMarginBottom":"10px","btnFontSize":"var(--lia-bs-font-size-sm)","focusBoxShadow":"0 0 0 3px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","checkLabelMarginBottom":"2px","checkboxBorderRadius":"3px","borderRadiusSm":"var(--lia-bs-border-radius-sm)","borderRadius":"var(--lia-bs-border-radius)","borderRadiusLg":"var(--lia-bs-border-radius-lg)","formTextMarginTop":"4px","textAreaBorderRadius":"var(--lia-bs-border-radius)","activeFillColor":"var(--lia-bs-primary)","__typename":"InputThemeSettings"},"loading":{"dotDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.2)","dotLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.5)","barDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.06)","barLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.4)","__typename":"LoadingThemeSettings"},"link":{"color":"var(--lia-bs-primary)","hoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) - 10%))","decoration":"none","hoverDecoration":"underline","__typename":"LinkThemeSettings"},"listGroup":{"itemPaddingY":"15px","itemPaddingX":"15px","borderColor":"var(--lia-bs-gray-300)","__typename":"ListGroupThemeSettings"},"modal":{"contentTextColor":"var(--lia-bs-body-color)","contentBg":"var(--lia-bs-white)","backgroundBg":"var(--lia-bs-black)","smSize":"440px","mdSize":"760px","lgSize":"1080px","backdropOpacity":0.3,"contentBoxShadowXs":"var(--lia-bs-box-shadow-sm)","contentBoxShadow":"var(--lia-bs-box-shadow)","headerFontWeight":"700","__typename":"ModalThemeSettings"},"navbar":{"position":"FIXED","background":{"attachment":null,"clip":null,"color":"var(--lia-bs-white)","imageAssetName":null,"imageLastModified":"0","origin":null,"position":"CENTER_CENTER","repeat":"NO_REPEAT","size":"COVER","__typename":"BackgroundProps"},"backgroundOpacity":0.8,"paddingTop":"15px","paddingBottom":"15px","borderBottom":"1px solid var(--lia-bs-border-color)","boxShadow":"var(--lia-bs-box-shadow-sm)","brandMarginRight":"30px","brandMarginRightSm":"10px","brandLogoHeight":"30px","linkGap":"10px","linkJustifyContent":"flex-start","linkPaddingY":"5px","linkPaddingX":"10px","linkDropdownPaddingY":"9px","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkColor":"var(--lia-bs-body-color)","linkHoverColor":"var(--lia-bs-primary)","linkFontSize":"var(--lia-bs-font-size-sm)","linkFontStyle":"NORMAL","linkFontWeight":"400","linkTextTransform":"NONE","linkLetterSpacing":"normal","linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkBgColor":"transparent","linkBgHoverColor":"transparent","linkBorder":"none","linkBorderHover":"none","linkBoxShadow":"none","linkBoxShadowHover":"none","linkTextBorderBottom":"none","linkTextBorderBottomHover":"none","dropdownPaddingTop":"10px","dropdownPaddingBottom":"15px","dropdownPaddingX":"10px","dropdownMenuOffset":"2px","dropdownDividerMarginTop":"10px","dropdownDividerMarginBottom":"10px","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","controllerIconColor":"var(--lia-bs-body-color)","controllerIconHoverColor":"var(--lia-bs-body-color)","controllerTextColor":"var(--lia-nav-controller-icon-color)","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","controllerHighlightColor":"hsla(30, 100%, 50%)","controllerHighlightTextColor":"var(--lia-yiq-light)","controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerColor":"var(--lia-nav-controller-icon-color)","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","hamburgerBgColor":"transparent","hamburgerBgHoverColor":"transparent","hamburgerBorder":"none","hamburgerBorderHover":"none","collapseMenuMarginLeft":"20px","collapseMenuDividerBg":"var(--lia-nav-link-color)","collapseMenuDividerOpacity":0.16,"__typename":"NavbarThemeSettings"},"pager":{"textColor":"var(--lia-bs-link-color)","textFontWeight":"var(--lia-font-weight-md)","textFontSize":"var(--lia-bs-font-size-sm)","__typename":"PagerThemeSettings"},"panel":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-bs-border-radius)","borderColor":"var(--lia-bs-border-color)","boxShadow":"none","__typename":"PanelThemeSettings"},"popover":{"arrowHeight":"8px","arrowWidth":"16px","maxWidth":"300px","minWidth":"100px","headerBg":"var(--lia-bs-white)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius)","boxShadow":"0 0.5rem 1rem hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.15)","__typename":"PopoverThemeSettings"},"prism":{"color":"#000000","bgColor":"#f5f2f0","fontFamily":"var(--font-family-monospace)","fontSize":"var(--lia-bs-font-size-base)","fontWeightBold":"var(--lia-bs-font-weight-bold)","fontStyleItalic":"italic","tabSize":2,"highlightColor":"#b3d4fc","commentColor":"#62707e","punctuationColor":"#6f6f6f","namespaceOpacity":"0.7","propColor":"#990055","selectorColor":"#517a00","operatorColor":"#906736","operatorBgColor":"hsla(0, 0%, 100%, 0.5)","keywordColor":"#0076a9","functionColor":"#d3284b","variableColor":"#c14700","__typename":"PrismThemeSettings"},"rte":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":" var(--lia-panel-box-shadow)","customColor1":"#bfedd2","customColor2":"#fbeeb8","customColor3":"#f8cac6","customColor4":"#eccafa","customColor5":"#c2e0f4","customColor6":"#2dc26b","customColor7":"#f1c40f","customColor8":"#e03e2d","customColor9":"#b96ad9","customColor10":"#3598db","customColor11":"#169179","customColor12":"#e67e23","customColor13":"#ba372a","customColor14":"#843fa1","customColor15":"#236fa1","customColor16":"#ecf0f1","customColor17":"#ced4d9","customColor18":"#95a5a6","customColor19":"#7e8c8d","customColor20":"#34495e","customColor21":"#000000","customColor22":"#ffffff","defaultMessageHeaderMarginTop":"14px","defaultMessageHeaderMarginBottom":"10px","defaultMessageItemMarginTop":"0","defaultMessageItemMarginBottom":"10px","diffAddedColor":"hsla(170, 53%, 51%, 0.4)","diffChangedColor":"hsla(43, 97%, 63%, 0.4)","diffNoneColor":"hsla(0, 0%, 80%, 0.4)","diffRemovedColor":"hsla(9, 74%, 47%, 0.4)","specialMessageHeaderMarginTop":"14px","specialMessageHeaderMarginBottom":"10px","specialMessageItemMarginTop":"0","specialMessageItemMarginBottom":"10px","__typename":"RteThemeSettings"},"tags":{"bgColor":"var(--lia-bs-gray-200)","bgHoverColor":"var(--lia-bs-gray-400)","borderRadius":"var(--lia-bs-border-radius-sm)","color":"var(--lia-bs-body-color)","hoverColor":"var(--lia-bs-body-color)","fontWeight":"var(--lia-font-weight-md)","fontSize":"var(--lia-font-size-xxs)","textTransform":"UPPERCASE","letterSpacing":"0.5px","__typename":"TagsThemeSettings"},"toasts":{"borderRadius":"var(--lia-bs-border-radius)","paddingX":"12px","__typename":"ToastsThemeSettings"},"typography":{"fontFamilyBase":"Atkinson Hyperlegible","fontStyleBase":"NORMAL","fontWeightBase":"400","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.3","fontSizeBase":"15px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"13px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[],"__typename":"TypographyThemeSettings"},"unstyledListItem":{"marginBottomSm":"5px","marginBottomMd":"10px","marginBottomLg":"15px","marginBottomXl":"20px","marginBottomXxl":"25px","__typename":"UnstyledListItemThemeSettings"},"yiq":{"light":"#ffffff","dark":"#000000","__typename":"YiqThemeSettings"},"colorLightness":{"primaryDark":0.36,"primaryLight":0.74,"primaryLighter":0.89,"primaryLightest":0.95,"infoDark":0.39,"infoLight":0.72,"infoLighter":0.85,"infoLightest":0.93,"successDark":0.24,"successLight":0.62,"successLighter":0.8,"successLightest":0.91,"warningDark":0.39,"warningLight":0.68,"warningLighter":0.84,"warningLightest":0.93,"dangerDark":0.41,"dangerLight":0.72,"dangerLighter":0.89,"dangerLightest":0.95,"__typename":"ColorLightnessThemeSettings"},"localOverride":false,"__typename":"Theme"},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1728320186000","value":{"email.verification.title":"Email Verification Required","email.verification.message.update.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. To change your email, visit My Settings.","email.verification.message.resend.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. Resend email."},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1728320186000","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:quilt:f5.prod:pages/kbs/TkbMessagePage:board:codeshare-1737018048874":{"__typename":"CachedAsset","id":"quilt:f5.prod:pages/kbs/TkbMessagePage:board:codeshare-1737018048874","value":{"id":"TkbMessagePage","container":{"id":"Common","headerProps":{"backgroundImageProps":null,"backgroundColor":null,"addComponents":null,"removeComponents":["community.widget.bannerWidget"],"componentOrder":null,"__typename":"QuiltContainerSectionProps"},"headerComponentProps":{"community.widget.breadcrumbWidget":{"disableLastCrumbForDesktop":false}},"footerProps":null,"footerComponentProps":null,"items":[{"id":"message-list","layout":"MAIN_SIDE","bgColor":"transparent","showTitle":true,"showDescription":true,"textPosition":"CENTER","textColor":"var(--lia-bs-body-color)","sectionEditLevel":null,"bgImage":null,"disableSpacing":null,"edgeToEdgeDisplay":null,"fullHeight":null,"showBorder":null,"__typename":"MainSideQuiltSection","columnMap":{"main":[{"id":"tkbs.widget.tkbArticleWidget","className":"lia-tkb-container","props":{"contributorListType":"panel","showHelpfulness":false,"showTimestamp":true,"showGuideNavigationSection":true,"showVersion":true,"lazyLoad":false,"editLevel":"CONFIGURE"},"__typename":"QuiltComponent"}],"side":[{"id":"featuredWidgets.widget.featuredContentWidget","className":null,"props":{"instanceId":"featuredWidgets.widget.featuredContentWidget-1702666556326","layoutProps":{"layout":"card","layoutOptions":{"useRepliesCount":false,"useAuthorRank":false,"useTimeToRead":true,"useKudosCount":false,"useViewCount":true,"usePreviewMedia":true,"useBody":false,"useCenteredCardContent":false,"useTags":true,"useTimestamp":false,"useBoardLink":true,"useAuthorLink":false,"useSolvedBadge":true}},"titleSrOnly":false,"showPager":true,"pageSize":3,"lazyLoad":true},"__typename":"QuiltComponent"},{"id":"messages.widget.relatedContentWidget","className":null,"props":{"hideIfEmpty":true,"enablePagination":true,"useTitle":true,"listVariant":{"type":"listGroup"},"pageSize":3,"style":"list","pagerVariant":{"type":"loadMore"},"viewVariant":{"type":"inline","props":{"useRepliesCount":true,"useMedia":true,"useAuthorRank":false,"useNode":true,"useTimeToRead":true,"useSpoilerFreeBody":true,"useKudosCount":true,"useNodeLink":true,"useViewCount":true,"usePreviewMedia":false,"useBody":false,"timeStampType":"postTime","useTags":true,"clampSubjectLines":2,"useBoardIcon":false,"useMessageTimeLink":true,"clampBodyLines":3,"useTextBody":true,"useSolvedBadge":true,"useAvatar":true,"useAuthorLogin":true,"useUnreadCount":true}},"lazyLoad":true,"panelType":"divider"},"__typename":"QuiltComponent"}],"__typename":"MainSideSectionColumns"}}],"__typename":"QuiltContainer"},"__typename":"Quilt","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-pages/kbs/TkbMessagePage-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-pages/kbs/TkbMessagePage-1728320186000","value":{"title":"{contextMessageSubject} | {communityTitle}","errorMissing":"This article cannot be found","name":"TKB Message Page","section.message-list.title":"","archivedMessageTitle":"This Content Has Been Archived","section.erPqcf.title":"","section.erPqcf.description":"","section.message-list.description":""},"localOverride":false},"CachedAsset:quiltWrapper:f5.prod:Common:1737017987096":{"__typename":"CachedAsset","id":"quiltWrapper:f5.prod:Common:1737017987096","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":"header.jpg","backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"LEFT_CENTER","lastModified":"1702932449000","__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"custom.widget.Beta_MetaNav","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"community.widget.navbarWidget","props":{"showUserName":false,"showRegisterLink":true,"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","linkFontWeight":"700","controllerHighlightColor":"hsla(30, 100%, 50%)","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkFontSize":"15px","linkBoxShadowHover":"none","backgroundOpacity":0.4,"controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerBgColor":"transparent","linkTextBorderBottom":"none","hamburgerColor":"var(--lia-nav-controller-icon-color)","brandLogoHeight":"48px","linkLetterSpacing":"normal","linkBgHoverColor":"transparent","collapseMenuDividerOpacity":0.16,"paddingBottom":"10px","dropdownPaddingBottom":"15px","dropdownMenuOffset":"2px","hamburgerBgHoverColor":"transparent","borderBottom":"0","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","linkJustifyContent":"center","linkColor":"var(--lia-bs-primary)","collapseMenuDividerBg":"var(--lia-nav-link-color)","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","background":{"imageAssetName":"","color":"var(--lia-bs-white)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-primary)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid #0C5C8D","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","linkPaddingX":"10px","paddingTop":"10px","linkPaddingY":"5px","linkTextTransform":"NONE","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkBgColor":"transparent","linkDropdownPaddingY":"9px","controllerIconColor":"#0C5C8D","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"#0C5C8D"},"links":{"sideLinks":[],"mainLinks":[{"children":[{"linkType":"INTERNAL","id":"migrated-link-1","params":{"boardId":"TechnicalForum","categoryId":"Forums"},"routeName":"ForumBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-2","params":{"boardId":"WaterCooler","categoryId":"Forums"},"routeName":"ForumBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-0","params":{"categoryId":"Forums"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-4","params":{"boardId":"codeshare","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-5","params":{"boardId":"communityarticles","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-3","params":{"categoryId":"CrowdSRC"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-7","params":{"boardId":"TechnicalArticles","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"article-series","params":{"boardId":"article-series","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"security-insights","params":{"boardId":"security-insights","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-8","params":{"boardId":"DevCentralNews","categoryId":"Articles"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-6","params":{"categoryId":"Articles"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-10","params":{"categoryId":"CommunityGroups"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"migrated-link-11","params":{"categoryId":"F5-Groups"},"routeName":"CategoryPage"}],"linkType":"INTERNAL","id":"migrated-link-9","params":{"categoryId":"GroupsCategory"},"routeName":"CategoryPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-12","params":{"boardId":"Events","categoryId":"top"},"routeName":"EventBoardPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-13","params":{"boardId":"Suggestions","categoryId":"top"},"routeName":"IdeaBoardPage"}]},"className":"QuiltComponent_lia-component-edit-mode__lQ9Z6","showSearchIcon":false},"__typename":"QuiltComponent"},{"id":"community.widget.bannerWidget","props":{"backgroundColor":"transparent","visualEffects":{"showBottomBorder":false},"backgroundImageProps":{"backgroundSize":"COVER","backgroundPosition":"CENTER_CENTER","backgroundRepeat":"NO_REPEAT"},"fontColor":"#222222"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"var(--lia-bs-primary)","linkHighlightColor":"#FFFFFF","visualEffects":{"showBottomBorder":false},"backgroundOpacity":60,"linkTextColor":"#FFFFFF"},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"footer":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"var(--lia-bs-body-color)","items":[{"id":"custom.widget.Beta_Footer","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Tag_Manager_Helper","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Consent_Blackbar","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"__typename":"QuiltWrapper","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-components/common/ActionFeedback-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1728320186000","value":{"joinedGroupHub.title":"Welcome","joinedGroupHub.message":"You are now a member of this group and are subscribed to updates.","groupHubInviteNotFound.title":"Invitation Not Found","groupHubInviteNotFound.message":"Sorry, we could not find your invitation to the group. The owner may have canceled the invite.","groupHubNotFound.title":"Group Not Found","groupHubNotFound.message":"The grouphub you tried to join does not exist. It may have been deleted.","existingGroupHubMember.title":"Already Joined","existingGroupHubMember.message":"You are already a member of this group.","accountLocked.title":"Account Locked","accountLocked.message":"Your account has been locked due to multiple failed attempts. Try again in {lockoutTime} minutes.","editedGroupHub.title":"Changes Saved","editedGroupHub.message":"Your group has been updated.","leftGroupHub.title":"Goodbye","leftGroupHub.message":"You are no longer a member of this group and will not receive future updates.","deletedGroupHub.title":"Deleted","deletedGroupHub.message":"The group has been deleted.","groupHubCreated.title":"Group Created","groupHubCreated.message":"{groupHubName} is ready to use","accountClosed.title":"Account Closed","accountClosed.message":"The account has been closed and you will now be redirected to the homepage","resetTokenExpired.title":"Reset Password Link has Expired","resetTokenExpired.message":"Try resetting your password again","invalidUrl.title":"Invalid URL","invalidUrl.message":"The URL you're using is not recognized. Verify your URL and try again.","accountClosedForUser.title":"Account Closed","accountClosedForUser.message":"{userName}'s account is closed","inviteTokenInvalid.title":"Invitation Invalid","inviteTokenInvalid.message":"Your invitation to the community has been canceled or expired.","inviteTokenError.title":"Invitation Verification Failed","inviteTokenError.message":"The url you are utilizing is not recognized. Verify your URL and try again","pageNotFound.title":"Access Denied","pageNotFound.message":"You do not have access to this area of the community or it doesn't exist","eventAttending.title":"Responded as Attending","eventAttending.message":"You'll be notified when there's new activity and reminded as the event approaches","eventInterested.title":"Responded as Interested","eventInterested.message":"You'll be notified when there's new activity and reminded as the event approaches","eventNotFound.title":"Event Not Found","eventNotFound.message":"The event you tried to respond to does not exist.","redirectToRelatedPage.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.message":"The content you are trying to access is archived","redirectToRelatedPage.message":"The content you are trying to access is archived","relatedUrl.archivalLink.flyoutMessage":"The content you are trying to access is archived View Archived Content"},"localOverride":false},"CachedAsset:component:custom.widget.Beta_MetaNav-en-1737018068310":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_MetaNav-en-1737018068310","value":{"component":{"id":"custom.widget.Beta_MetaNav","template":{"id":"Beta_MetaNav","markupLanguage":"HANDLEBARS","style":null,"texts":null,"defaults":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_MetaNav","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Beta_Footer-en-1737018068310":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_Footer-en-1737018068310","value":{"component":{"id":"custom.widget.Beta_Footer","template":{"id":"Beta_Footer","markupLanguage":"HANDLEBARS","style":null,"texts":null,"defaults":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_Footer","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Tag_Manager_Helper-en-1737018068310":{"__typename":"CachedAsset","id":"component:custom.widget.Tag_Manager_Helper-en-1737018068310","value":{"component":{"id":"custom.widget.Tag_Manager_Helper","template":{"id":"Tag_Manager_Helper","markupLanguage":"HANDLEBARS","style":null,"texts":null,"defaults":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Tag_Manager_Helper","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Consent_Blackbar-en-1737018068310":{"__typename":"CachedAsset","id":"component:custom.widget.Consent_Blackbar-en-1737018068310","value":{"component":{"id":"custom.widget.Consent_Blackbar","template":{"id":"Consent_Blackbar","markupLanguage":"HTML","style":null,"texts":null,"defaults":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Consent_Blackbar","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"dynamicByCoreNode":false,"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:text:en_US-components/community/Breadcrumb-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1728320186000","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBanner-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBanner-1728320186000","value":{"messageMarkedAsSpam":"This post has been marked as spam","messageMarkedAsSpam@board:TKB":"This article has been marked as spam","messageMarkedAsSpam@board:BLOG":"This post has been marked as spam","messageMarkedAsSpam@board:FORUM":"This discussion has been marked as spam","messageMarkedAsSpam@board:OCCASION":"This event has been marked as spam","messageMarkedAsSpam@board:IDEA":"This idea has been marked as spam","manageSpam":"Manage Spam","messageMarkedAsAbuse":"This post has been marked as abuse","messageMarkedAsAbuse@board:TKB":"This article has been marked as abuse","messageMarkedAsAbuse@board:BLOG":"This post has been marked as abuse","messageMarkedAsAbuse@board:FORUM":"This discussion has been marked as abuse","messageMarkedAsAbuse@board:OCCASION":"This event has been marked as abuse","messageMarkedAsAbuse@board:IDEA":"This idea has been marked as abuse","preModCommentAuthorText":"This comment will be published as soon as it is approved","preModCommentModeratorText":"This comment is awaiting moderation","messageMarkedAsOther":"This post has been rejected due to other reasons","messageMarkedAsOther@board:TKB":"This article has been rejected due to other reasons","messageMarkedAsOther@board:BLOG":"This post has been rejected due to other reasons","messageMarkedAsOther@board:FORUM":"This discussion has been rejected due to other reasons","messageMarkedAsOther@board:OCCASION":"This event has been rejected due to other reasons","messageMarkedAsOther@board:IDEA":"This idea has been rejected due to other reasons","messageArchived":"This post was archived on {date}","relatedUrl":"View Related Content","relatedContentText":"Showing related content","archivedContentLink":"View Archived Content"},"localOverride":false},"CachedAsset:text:en_US-components/tkbs/TkbArticleWidget-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/tkbs/TkbArticleWidget-1728320186000","value":{},"localOverride":false},"Category:category:Forums":{"__typename":"Category","id":"category:Forums","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Forum:board:TechnicalForum":{"__typename":"Forum","id":"board:TechnicalForum","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Forum:board:WaterCooler":{"__typename":"Forum","id":"board:WaterCooler","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Articles":{"__typename":"Category","id":"category:Articles","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:TechnicalArticles":{"__typename":"Tkb","id":"board:TechnicalArticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:DevCentralNews":{"__typename":"Tkb","id":"board:DevCentralNews","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:GroupsCategory":{"__typename":"Category","id":"category:GroupsCategory","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:F5-Groups":{"__typename":"Category","id":"category:F5-Groups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:CommunityGroups":{"__typename":"Category","id":"category:CommunityGroups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Occasion:board:Events":{"__typename":"Occasion","id":"board:Events","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"occasionPolicies":{"__typename":"OccasionPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Idea:board:Suggestions":{"__typename":"Idea","id":"board:Suggestions","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"ideaPolicies":{"__typename":"IdeaPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:communityarticles":{"__typename":"Tkb","id":"board:communityarticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:security-insights":{"__typename":"Tkb","id":"board:security-insights","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:article-series":{"__typename":"Tkb","id":"board:article-series","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"CachedAsset:text:en_US-components/customComponent/CustomComponent-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/customComponent/CustomComponent-1728320186000","value":{"errorMessage":"Error rendering component id: {customComponentId}","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/community/Navbar-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1728320186000","value":{"community":"Community Home","inbox":"Inbox","manageContent":"Manage Content","tos":"Terms of Service","forgotPassword":"Forgot Password","themeEditor":"Theme Editor","edit":"Edit Navigation Bar","skipContent":"Skip to content","migrated-link-9":"Groups","migrated-link-7":"Technical Articles","migrated-link-8":"DevCentral News","migrated-link-1":"Technical Forum","migrated-link-10":"Community Groups","migrated-link-2":"Water Cooler","migrated-link-11":"F5 Groups","migrated-link-0":"Forums","article-series":"Article Series","migrated-link-5":"Community Articles","migrated-link-6":"Articles","security-insights":"Security Insights","migrated-link-3":"CrowdSRC","migrated-link-4":"CodeShare","migrated-link-12":"Events","migrated-link-13":"Suggestions"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarHamburgerDropdown-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1728320186000","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1728320186000","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1728320186000","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1728320186000","value":{"title.login":"Sign In","title.registration":"Register","title.forgotPassword":"Forgot Password","title.multiAuthLogin":"Sign In"},"localOverride":false},"CachedAsset:text:en_US-components/nodes/NodeLink-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1728320186000","value":{"place":"Place {name}"},"localOverride":false},"QueryVariables:TopicReplyList:message:280534:1":{"__typename":"QueryVariables","id":"TopicReplyList:message:280534:1","value":{"id":"message:280534","first":10,"sorts":{"postTime":{"direction":"ASC"}},"repliesFirst":3,"repliesFirstDepthThree":1,"repliesSorts":{"postTime":{"direction":"ASC"}},"useAvatar":true,"useAuthorLogin":true,"useAuthorRank":true,"useBody":true,"useKudosCount":true,"useTimeToRead":false,"useMedia":false,"useReadOnlyIcon":false,"useRepliesCount":true,"useSearchSnippet":false,"useAcceptedSolutionButton":false,"useSolvedBadge":false,"useAttachments":false,"attachmentsFirst":5,"useTags":true,"useNodeAncestors":false,"useUserHoverCard":true,"useNodeHoverCard":false,"useModerationStatus":true,"usePreviewSubjectModal":false,"useMessageStatus":true}},"ROOT_MUTATION":{"__typename":"Mutation"},"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1728320186000","value":{"title":"Query Handler"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1728320186000","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewStandard-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewStandard-1728320186000","value":{"anonymous":"Anonymous","author":"{messageAuthorLogin}","authorBy":"{messageAuthorLogin}","board":"{messageBoardTitle}","replyToUser":" to {parentAuthor}","showMoreReplies":"Show More","replyText":"Reply","repliesText":"Replies","markedAsSolved":"Marked as Solved","movedMessagePlaceholder.BLOG":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.TKB":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.FORUM":"{count, plural, =0 {This reply has been} other {These replies have been} }","movedMessagePlaceholder.IDEA":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.OCCASION":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholderUrlText":"moved.","messageStatus":"Status: ","statusChanged":"Status changed: {previousStatus} to {currentStatus}","statusAdded":"Status added: {status}","statusRemoved":"Status removed: {status}","labelExpand":"expand replies","labelCollapse":"collapse replies","unhelpfulReason.reason1":"Content is outdated","unhelpfulReason.reason2":"Article is missing information","unhelpfulReason.reason3":"Content is for a different Product","unhelpfulReason.reason4":"Doesn't match what I was searching for"},"localOverride":false},"CachedAsset:text:en_US-components/messages/ThreadedReplyList-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/ThreadedReplyList-1728320186000","value":{"title":"{count, plural, one{# Reply} other{# Replies}}","title@board:BLOG":"{count, plural, one{# Comment} other{# Comments}}","title@board:TKB":"{count, plural, one{# Comment} other{# Comments}}","title@board:IDEA":"{count, plural, one{# Comment} other{# Comments}}","title@board:OCCASION":"{count, plural, one{# Comment} other{# Comments}}","noRepliesTitle":"No Replies","noRepliesTitle@board:BLOG":"No Comments","noRepliesTitle@board:TKB":"No Comments","noRepliesTitle@board:IDEA":"No Comments","noRepliesTitle@board:OCCASION":"No Comments","noRepliesDescription":"Be the first to reply","noRepliesDescription@board:BLOG":"Be the first to comment","noRepliesDescription@board:TKB":"Be the first to comment","noRepliesDescription@board:IDEA":"Be the first to comment","noRepliesDescription@board:OCCASION":"Be the first to comment","messageReadOnlyAlert:BLOG":"Comments have been turned off for this post","messageReadOnlyAlert:TKB":"Comments have been turned off for this article","messageReadOnlyAlert:IDEA":"Comments have been turned off for this idea","messageReadOnlyAlert:FORUM":"Replies have been turned off for this discussion","messageReadOnlyAlert:OCCASION":"Comments have been turned off for this event"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyCallToAction-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyCallToAction-1728320186000","value":{"leaveReply":"Leave a reply...","leaveReply@board:BLOG@message:root":"Leave a comment...","leaveReply@board:TKB@message:root":"Leave a comment...","leaveReply@board:IDEA@message:root":"Leave a comment...","leaveReply@board:OCCASION@message:root":"Leave a comment...","repliesTurnedOff.FORUM":"Replies are turned off for this topic","repliesTurnedOff.BLOG":"Comments are turned off for this topic","repliesTurnedOff.TKB":"Comments are turned off for this topic","repliesTurnedOff.IDEA":"Comments are turned off for this topic","repliesTurnedOff.OCCASION":"Comments are turned off for this topic","infoText":"Stop poking me!"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1728320186000","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1728320186000","value":{"showMessageBody":"Show More","mentionsErrorTitle":"{mentionsType, select, board {Board} user {User} message {Message} other {}} No Longer Available","mentionsErrorMessage":"The {mentionsType} you are trying to view has been removed from the community.","videoProcessing":"Video is being processed. Please try again in a few minutes.","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageCustomFields-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageCustomFields-1728320186000","value":{"CustomField.default.label":"Value of {name}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageRevision-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRevision-1728320186000","value":{"lastUpdatedDatePublished":"{publishCount, plural, one{Published} other{Updated}} {date}","lastUpdatedDateDraft":"Created {date}","version":"Version {major}.{minor}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyButton-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyButton-1728320186000","value":{"repliesCount":"{count}","title":"Reply","title@board:BLOG@message:root":"Comment","title@board:TKB@message:root":"Comment","title@board:IDEA@message:root":"Comment","title@board:OCCASION@message:root":"Comment"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageAuthorBio-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageAuthorBio-1728320186000","value":{"sendMessage":"Send Message","actionMessage":"Follow this blog board to get notified when there's new activity","coAuthor":"CO-PUBLISHER","contributor":"CONTRIBUTOR","userProfile":"View Profile","iconlink":"Go to {name} {type}"},"localOverride":false},"CachedAsset:text:en_US-components/guides/GuideBottomNavigation-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/guides/GuideBottomNavigation-1728320186000","value":{"nav.label":"Previous/Next Page","nav.previous":"Previous","nav.next":"Next"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1728320186000","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserRank-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserRank-1728320186000","value":{"rankName":"{rankName}","userRank":"Author rank {rankName}"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserRegistrationDate-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserRegistrationDate-1728320186000","value":{"noPrefix":"{date}","withPrefix":"Joined {date}"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagView/TagViewChip-1728320186000","value":{"tagLabelName":"Tag name {tagName}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1728320186000","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1728320186000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/ranks/UserRankLabel-1728320186000","value":{"altTitle":"Icon for {rankName} rank"},"localOverride":false}}}},"page":"/kbs/TkbMessagePage/TkbMessagePage","query":{"boardId":"codeshare","messageSubject":"http-session-watcher","messageId":"280534"},"buildId":"OKtI0OLKuXmERTJKBVqYX","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"f5","openTelemetryServiceVersion":"24.11.0","openTelemetryUniverse":"prod","openTelemetryCollector":"http://localhost:4318","openTelemetryRouteChangeAllowedTime":"5000","apolloDevToolsEnabled":false},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["./components/customComponent/CustomComponent/CustomComponent.tsx","./components/community/Navbar/NavbarWidget.tsx","./components/community/Breadcrumb/BreadcrumbWidget.tsx","./components/tkbs/TkbArticleWidget/TkbArticleWidget.tsx","./components/messages/MessageView/MessageViewStandard/MessageViewStandard.tsx","./components/messages/ThreadedReplyList/ThreadedReplyList.tsx","../shared/client/components/common/List/UnwrappedList/UnwrappedList.tsx","./components/tags/TagView/TagView.tsx","./components/tags/TagView/TagViewChip/TagViewChip.tsx"],"appGip":true,"scriptLoader":[]}