Forum Discussion

ken_ucs's avatar
ken_ucs
Icon for Nimbostratus rankNimbostratus
Jun 10, 2014

Error log "operation not supported....." when applied secondary irule to VS

I have applied the first irule "HTTPS_retry_prod" and it was working fine. During the maintenance, I applied the secondary irule "isolation_redirect" to redirect all user to the announcement page except allowed user. But I found the error log was shown continually as below. "HTTPS_retry_prod_3_logging - Operation not supported (line 14) invoked from within "HTTP::collect $content_length"

Is it caused by the duplicate event "HTTP_REQUEST" in each irule

HTTPS_retry_prod

when CLIENT_ACCEPTED { Save the name of the virtual server default pool set def_pool [LB::server pool]

On each new TCP connection track that we have not retried a request yet

set max_retries [active_members $def_pool] set retries 0 } when HTTP_REQUEST {

Only save the request headers if this is not a retried request

if { $retries == 0 } { set request_headers [HTTP::request] if { [HTTP::method] eq "POST" } { Trigger collection for up to 1MB of data if { [HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576 } { set content_length [HTTP::header "Content-Length"] } else { set content_length 1048576 }

   Check if $content_length is not set to 0
  if { $content_length > 0 } {
    HTTP::collect $content_length
  }
}

} } when HTTP_REQUEST_DATA { do stuff with the payload set payload [HTTP::payload] Append HTTP payload to HTTP request header to form a complete HTTP post request (request + payload) append request_headers [HTTP::payload [HTTP::payload length]] } when LB_SELECTED {

Select a new pool member from the VS default pool if we are retrying this request

if { $retries > 0 } { + log selected member when retry log local0. "Retry selected : server=[IP::server_addr] client=[IP::client_addr]" LB::reselect pool $def_pool } } when LB_FAILED { log local0. "LB fail : server=[IP::server_addr] client=[IP::client_addr]" LB::reselect pool $def_pool } when HTTP_RESPONSE {

Check for server errors

if { [HTTP::status] >= 500 } { Server error, retry the request if we have not already retried more times than there are pool members incr retries log local0. "Response error : server=[IP::server_addr] client=[IP::client_addr] retry=$retries max_retries=$max_retries" if { $retries < $max_retries } { log retry header log local0. "HTTP retry : server=[IP::server_addr] client=[IP::client_addr] header=[substr $request_headers 0 '?']" HTTP::retry $request_headers Exit this event from this iRule so we do not reset retries to 0 return } + retry reach maximum no. of time, log the event log local0. "Retry maximum : server=[IP::server_addr] client=[IP::client_addr] max_retries=$max_retries" } If we are still in the rule we are not retrying this request set retries 0 }

isolation_redirect

when HTTP_REQUEST { if { [class match [IP::client_addr] equals "lms_support_data_group"] } { log local0. "Client [IP::client_addr] allowed" } else { HTTP::redirect "http://www.polyu.edu.hk/elearning/announcement/" log local0. "Client [IP::client_addr] isn't allowed , Action redirect" } }

  • Hi Ken! Sorry, but your post is virtually unreadable. :) Try using the preformatted code to display your irule. Mark the irule code, then control+K to use it. /Patrik
  • Hi Patrik , Thanks for reminding ! Below is the irule.

     HTTPS_retry_prod
    when CLIENT_ACCEPTED {
       Save the name of the virtual server default pool
      set def_pool [LB::server pool]
     On each new TCP connection track that we have not retried a request yet
      set max_retries [active_members $def_pool]
      set retries 0
    }
    when HTTP_REQUEST {
     Only save the request headers if this is not a retried request
      if { $retries == 0 } {
        set request_headers [HTTP::request]
    if { [HTTP::method] eq "POST" } {
           Trigger collection for up to 1MB of data
          if { [HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576 } {
            set content_length [HTTP::header "Content-Length"]
          } else {
            set content_length 1048576
          }
    
           Check if $content_length is not set to 0
          if { $content_length > 0 } {
            HTTP::collect $content_length
          }
        }
      }
    }
    when HTTP_REQUEST_DATA {
       do stuff with the payload
      set payload [HTTP::payload]
       Append HTTP payload to HTTP request header to form a complete HTTP post request (request + payload) 
      append request_headers [HTTP::payload [HTTP::payload length]]
    }
    when LB_SELECTED {
     Select a new pool member from the VS default pool if we are retrying this request
      if { $retries > 0 } {
        + log selected member when retry
        log local0. "Retry selected : server=[IP::server_addr] client=[IP::client_addr]"
        LB::reselect pool $def_pool
      }
    }
    when LB_FAILED {
      log local0. "LB fail : server=[IP::server_addr] client=[IP::client_addr]"
      LB::reselect pool $def_pool
    }
    when HTTP_RESPONSE {
     Check for server errors
      if { [HTTP::status] >= 500 } {
         Server error, retry the request if we have not already retried more times than there are pool members
        incr retries
        log local0. "Response error : server=[IP::server_addr] client=[IP::client_addr] retry=$retries max_retries=$max_retries"
    if { $retries < $max_retries } {
           log retry header
          log local0. "HTTP retry : server=[IP::server_addr] client=[IP::client_addr] header=[substr $request_headers 0 '?']"
          HTTP::retry $request_headers
           Exit this event from this iRule so we do not reset retries to 0
          return
        }
        + retry reach maximum no. of time, log the event
        log local0. "Retry maximum : server=[IP::server_addr] client=[IP::client_addr] max_retries=$max_retries"
      }
       If we are still in the rule we are not retrying this request
      set retries 0
    }
    
     isolation_redirect
    when HTTP_REQUEST {
      if { [class match [IP::client_addr] equals "lms_support_data_group"] } {
      log local0. "Client [IP::client_addr] allowed"
      } else {
      HTTP::redirect "http://www.polyu.edu.hk/elearning/announcement/"
      log local0. "Client [IP::client_addr] isn't allowed , Action redirect"
    }
    }
    
  • Hi!

    Try putting the isolation_redirect rule ahead of the HTTPS_retry_prod rule and do a check to see if a redirect has been issued or not.

    Ie.

     isolation_redirect
    when HTTP_REQUEST {
      if { [class match [IP::client_addr] equals "lms_support_data_group"] } {
      log local0. "Client [IP::client_addr] allowed"
      } else {
      HTTP::redirect "http://www.polyu.edu.hk/elearning/announcement/"
      A redirect has been sent, prevent the subsequent irule from being executed
      set redirect 1
      log local0. "Client [IP::client_addr] isn't allowed , Action redirect"
    }
    }
    

    Then enclose your HTTPS_retry_prod events in this if:

     HTTPS_retry_prod
    when CLIENT_ACCEPTED {
         Save the name of the virtual server default pool
        set def_pool [LB::server pool]
        On each new TCP connection track that we have not retried a request yet
        set max_retries [active_members $def_pool]
        set retries 0
    }
    when HTTP_REQUEST {
        if { !([info exists redirect] && $redirect == 1) }{
             Only save the request headers if this is not a retried request
            if { $retries == 0 } {
                set request_headers [HTTP::request]
                if { [HTTP::method] eq "POST" } {
                     Trigger collection for up to 1MB of data
                    if { [HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576 } {
                        set content_length [HTTP::header "Content-Length"]
                    } else {
                        set content_length 1048576
                    }
    
                     Check if $content_length is not set to 0
                    if { $content_length > 0 } {
                        HTTP::collect $content_length
                    }
                }
            }
        }
    }
    when HTTP_REQUEST_DATA {
        if { !([info exists redirect] && $redirect == 1) }{
             do stuff with the payload
            set payload [HTTP::payload]
             Append HTTP payload to HTTP request header to form a complete HTTP post request (request + payload) 
            append request_headers [HTTP::payload [HTTP::payload length]]
        }
    }
    when LB_SELECTED {
     Select a new pool member from the VS default pool if we are retrying this request
      if { $retries > 0 } {
        + log selected member when retry
        log local0. "Retry selected : server=[IP::server_addr] client=[IP::client_addr]"
        LB::reselect pool $def_pool
      }
    }
    when LB_FAILED {
      log local0. "LB fail : server=[IP::server_addr] client=[IP::client_addr]"
      LB::reselect pool $def_pool
    }
    
    when HTTP_RESPONSE {
        if { !([info exists redirect] && $redirect == 1) }{
             Check for server errors
            if { [HTTP::status] >= 500 } {
                 Server error, retry the request if we have not already retried more times than there are pool members
                incr retries
                log local0. "Response error : server=[IP::server_addr] client=[IP::client_addr] retry=$retries max_retries=$max_retries"
                if { $retries < $max_retries } {
                     log retry header
                    log local0. "HTTP retry : server=[IP::server_addr] client=[IP::client_addr] header=[substr $request_headers 0 '?']"
                    HTTP::retry $request_headers
                     Exit this event from this iRule so we do not reset retries to 0
                    return
                }
                + retry reach maximum no. of time, log the event
                log local0. "Retry maximum : server=[IP::server_addr] client=[IP::client_addr] max_retries=$max_retries"
            }
             If we are still in the rule we are not retrying this request
            set retries 0
        }
    }
    

    Also, I'd recommend adding this one to the top of the irule execution list to avoid mysterious problems later with clients re-using connections:

        Reset variables
        when HTTP_REQUEST {
            Reset the blocked variable before every execution.
            set redirect 0
        }
    

    So the irule execution order should look like this:

    1. Reset-Variables
    2. Isolation Redirect
    3. HTTPS_retry_prod

    /Patrik