Forum Discussion

Scott_85521's avatar
Scott_85521
Icon for Nimbostratus rankNimbostratus
Oct 28, 2008

Handle 4xx 5xx responses

Hey Guys,

 

I'm attempting to write an iRule to handle 4xx or 5xx HTTP status codes. The intention of the rule is to intercept the HTTP 4xx and 5xx responses, request/collect a friendly and prettily formatted error-page from a different URI/application, then pass back to the user the original response code with the prettily formatted error-page.

 

 

The problem, when the iRule from the below code is applied to the VIP, some applications work fine (as long as a 4xx or 5xx status is not thrown from the app) while others reset the connection or timeout. If someone can see something in the code below that may be causing this, or offer a better way to achieve the goal, it will be greatly appreciated.

 

 

 
 when CLIENT_ACCEPTED { 
   set error false  
 } 
  
   
 when HTTP_REQUEST { 
   set request [HTTP::request] 
 } 
  
   
 when LB_SELECTED { 
   log local0. "lbset: $error" 
   log local0. "lbset URI: [HTTP::uri]" 
   
 If we have re-slelcted based on the HTTP_Response, and an error exists 
 reselect the application servers that host the error page and rewrite the URI 
   if { $error ne false } { 
     HTTP::uri /app/errorpage 
     LB::reselect pool webpool.that.hosts.error.page            
   }     
 } 
   
  
 when HTTP_RESPONSE { 
   set status [HTTP::status] 
  
   log local0. "response Status: $status" 
  
  
   if { $error ne false } { 
 log local0. "response Collect $error" 
  
     if {[info exists [HTTP::header Content-Length]] } {   
        set clen [HTTP::header "Content-Length"] 
     } else {   
       set clen 4294967295 
     }    
     if { $clen > 0 } {   
       HTTP::collect $clen 
     }   
   } elseif { $status eq 200 } { 
     return 
   } elseif { ($status starts_with "4") or ($status starts_with "5") } { 
       set error $status  
   log local0. "response Error: $error" 
       HTTP::retry $request 
   } 
 } 
  
   
  
 when HTTP_RESPONSE_DATA { 
   log local0. "responding: $error" 
  
   if { $error ne false } { 
     HTTP::respond $error content [HTTP::payload] 
  } 
 } 
 

 

 

Thanks,

 

 

 

Scott-

3 Replies

  • Arie's avatar
    Arie
    Icon for Altostratus rankAltostratus
    Do you have any other iRules that use HTTP::respond and/or HTTP::redirect? You can fire them only once per connection.
  • We do, but they only trigger when the app is sending 200s, 301s or 302s. i.e. the conditions for each iRule do not overlap.
  • Do you see a TCL error when the connection is reset? If you grep through /var/log/ltm (grep -i 'tcl error' /var/log/ltm), do you see any errors? Are you able to reproduce the issue or get logs from such a failure? I wonder if it's an issue with collecting more data than TCL can handle. If that were the case you should see a TMM restart when the issue occurs.

     

     

    Also, do you need to collect the response data if you're just trying to reselect a member of a new pool? Couldn't you use HTTP::retry from HTTP_RESPONSE to retry the request without collecting the response payload?

     

     

    Aaron