HTTP::retry

Description

Re-sends a request to a server. Can be either the same or a different request, to the same or a different server.
  • To replay the same request, save the request to a variable in the HTTP_REQUEST event, then use it with this command.
  • A different request may alternatively be specified. The request string must be well-formed and complete, including all required headers.

The request generated by this command triggers HTTP_REQUEST and all subsequent client-side events.
Note: If you want to retry a request with a payload, you should use HTTP::collect to collect the payload and then append the payload to the request headers retrieved using HTTP::request in HTTP_REQUEST_DATA.

Syntax

HTTP::retry <request>

v11.5+
HTTP::retry [-reset] <request>

HTTP::retry <request>

  • Resends a request to a server. The request header must be well-formed and complete.

HTTP::retry [-reset]

  • Resends a request to a server and resets serverside connection instead of sinking the data.

Examples

# Retry requests to the virtual server's default pool if the server responds with an error code (5xx status)

when CLIENT_ACCEPTED {
   # On each new TCP connection track that we have not retried a request yet
   set retries 0

   # Save the name of the virtual server default pool
   set default_pool [LB::server pool]
}

when HTTP_REQUEST {
   # We only want to retry GET requests to avoid having to collect POST payloads
   # Only save the request headers if this is not a retried request
   if { [HTTP::method] eq "GET" && $retries == 0 }{
      set request_headers [HTTP::request]
      log local0. "Saving HTTP request headers: $request_headers"
   }
}

when LB_SELECTED {
   # Select a new pool member from the VS default pool if we are retrying this request
   if { $retries > 0 } {
      LB::reselect pool $default_pool
   }
}

when HTTP_RESPONSE {
   # Check for server errors
   if { [HTTP::status] starts_with "5" } {

      # Server error, retry the request if we have not already retried more times than there are pool members
      incr retries
      log local0. "5xx error caught: retry $retries out of [active_members $default_pool]"

      if { $retries < [active_members $default_pool] } {
         # Retry this request
         HTTP::retry $request_headers

         # Exit this event from this iRule so we do not reset retries to 0
         return
      }
   }
   # If we are still in the rule we are not retrying this request
   set retries 0
}

# Retry 404 responses once to a second pool
when CLIENT_ACCEPTED {

    # Track whether this is a retried request
    set retried 0

    # Save the name of the VS default pool
    set default_pool [LB::server pool]

    # Track whether we have the headers for this request
    set request_headers ""
}

when HTTP_REQUEST {

    # Select the VS default pool by default
    pool $default_pool


    # Check if this is a retried request
    if {$retried == 0}{

        # Only save request headers if it is a GET request
        # We do not want to retry requests with payloads
        if {[HTTP::method] eq "GET"}{

            # Save the HTTP request headers
            set request_headers [HTTP::request]
            log local0. "HTTP request: $request_headers"

        } else {

            # Null the headers to make sure we only retry GETs
            set request_headers ""
        }
    } else {
        # Select the other pool for the retry
        pool other_pool
    }
}

when HTTP_RESPONSE {

    # Check if we got a 404 from the default pool
    if { [HTTP::status] == 404 && $request_headers ne "" && [LB::server pool] eq $default_pool } {

        # Track that we are retrying this request
        set retried 1
        log local0. "404 error caught from default pool. Retrying."

        HTTP::retry $request_headers
    } else {
        # Track that we are retrying this request
        set retried 0
    }
}

# One can save a WAN round trip by following a redirect at the LTM and responding to the
# original client request with the result of the redirect
when HTTP_REQUEST {

   # Save the host header value
   set host [HTTP::host]
}
when HTTP_RESPONSE {

   # Check if response is a redirect based on the status code
   if { [HTTP::is_redirect] } {

      # Now generate a GET request to the new location
      HTTP::retry "GET [HTTP::header location] HTTP/1.1\r\nHost: $host\r\n\r\n"
   }
}