Conditioning iRule Logic on External Information - #01 - HTTP::retry
I have attempted to implement this and the request gets all the way through, is allowed and is retried, but on the second pass through the iRule when the request is sent to the correct pool the request never actually reaches the regular pool members.
when RULE_INIT {
set string to match for valid connection set valid_string "Sure" } when CLIENT_ACCEPTED { set flag to control logical flow. 1 means lookup is pending. set lookup 1 set string to match for valid connection set valid_string "Sure" } when HTTP_REQUEST { If each request on the same connection must force a lookup, re-initialize the value of the flag here In this case, lookup result based on client IP is good for the life of the connection, so we'll leave the flag alone here. set lookup 1 if {$lookup == 1} {
save the original request and original payload and payload length
set original_request [HTTP::request]
set original_payload [HTTP::payload]
set original_payload_length [HTTP::payload length]
if client hasn't already been looked up, save the
request so we can replay it to the LB server later;
set LB_request [HTTP::request]
set LB_uri [HTTP::uri]
inject lookup URI in place of original request;
HTTP::uri "/getAllowed?ip=[IP::client_addr]"
and send the out-of-band validation query to the geo_pool.
pool geo_pool
} else {
correct the request payload and content length
set retry_payload_length [HTTP::payload length]
HTTP::payload replace 0 $retry_payload_length $original_payload
if { [HTTP::header exists "Content-Length"] } {
HTTP::header replace "Content-Length" $original_payload_length
}
otherwise, send the request to the LB pool
pool reg_pool
} } when HTTP_RESPONSE { If lookup flag is still on in response event, this is the response to the lookup, so we collect entire payload (up to 1MB limit) both to evaluate the DB server response and to prevent this response from being returned to the client. Already-validated connections will bypass the rest of the rule. if {$lookup == 1}{ if {[HTTP::header exists Content-Length] && \ ([HTTP::header Content-Length] < 1048576)}{ set clength [HTTP::header Content-Length] } else { set clength 1048576 } HTTP::collect $clength } } when HTTP_RESPONSE_DATA { HTTP_RESPONSE_DATA will only be triggered for a DB lookup. (All other requests have already been forwarded to the LB pool.) If response from DB indicates connection is valid, reset the lookup flag & replay the request to the LB server. Otherwise, reject the connection
if {[HTTP::payload] contains $valid_string}{ set lookup 0 pool reg_pool HTTP::retry $LB_request } else { log "rejected" reject } depending on the app, reset the value of the flag here in case of new request on same connection (useful for situations where each URI requires a lookup) In this case, lookup result based on client IP is good for the life of the connection, so we'll leave the flag set to 0 set lookup 0 }