cancel
Showing results for 
Search instead for 
Did you mean: 

Error: read ECONNRESET error while using Postman for API calls after change to irule

krisnaseechurn
Altostratus
Altostratus

Am getting connection resets after modifying irule. Error is below:

TCL error: /Common/irule_172.29.8.1 <HTTP_RESPONSE> - can't use non-numeric string as operand of "&&" while executing "if { [HTTP::status] == "404" && {![HTTP::header] contains "Content-Type:application/json" && ![HTTP::header] contains "Content-Type:application/xml" &..."

The extract from the irule is below.

if { [HTTP::status] starts_with "4" && {[HTTP::header] contains "Content-Type:application/json" || [HTTP::header] contains "Content-Type:application/xml" || [HTTP::header] contains "Content-Type:application/problem+json"} } {
set irule "Irule_Catch_404"
set http_status [HTTP::status]
set res_start_time [clock format [clock seconds] -format "%Y/%m/%d %H:%M:%S"]
set req_elapsed_time [expr {[clock clicks -milliseconds] - $tcp_start_time}]
if { [HTTP::header exists "Content-Length"] } {
set req_length [HTTP::header "Content-Length"]
} else {
set req_length 0
}

there is no syntax error as I can save the changes but F5 logs show that connection is being reset

 

2 ACCEPTED SOLUTIONS

Hi @krisnaseechurn, the HTTP::redirect command is used a couple of times in your iRule.

It´s best practice, to use a "return" command afterwards and perhaps an "event disable" command to prevent the iRule from further execution.

Personally I´m trying to avoid the HTTP::redirect. Instead I prefer to use HTTP::respond because it´s providing very granular control about the exact status code (maybe you prefer a 301 instead of 302?). It also allows to add a Connection Close header. Along with an "event disable" command followed by a "return" you will definitely avoid further execution of the iRule event where the command was fired.

For debugging it would help to force an unwanted redirect and monitor the /var/log/ltm for log entries and TCL errors/warnings:

tail -f /var/log/ltm

 

View solution in original post

thanks for all the input..

the issue was it was missing an !

if { !([HTTP::status]=="500") && \

View solution in original post

5 REPLIES 5

Hi krisnaseechurn,

Can you use parentheses( ) instead of braces{ } in if condition?

 

when HTTP_RESPONSE {
	if { [HTTP::status] == 404 && ([HTTP::header] contains "Content-Type:application/json" || [HTTP::header] contains "Content-Type:application/xml" || [HTTP::header] contains "Content-Type:application/problem+json") } {
		set irule "Irule_Catch_404"
...

 

 

 

This one is working without errors:

when CLIENT_ACCEPTED {
  set tcp_start_time [clock clicks -milliseconds]
}
when HTTP_RESPONSE {
  if { ([HTTP::status] starts_with "4") && \
       ([HTTP::header Content-Type] contains "application/json" || \
        [HTTP::header Content-Type] contains "application/xml" || \
        [HTTP::header Content-Type] contains "application/problem+json") } {
    set irule "Irule_Catch_404"
    set http_status [HTTP::status]
    set resp_start_time [clock format [clock seconds] -format "%Y/%m/%d %H:%M:%S"]
    set resp_elapsed_time [expr {[clock clicks -milliseconds] - $tcp_start_time}]
    if { [HTTP::header exists "Content-Length"] } {
      set resp_length [HTTP::header "Content-Length"]
    }
  } else {
    set resp_length 0
  }
  log local0. "$resp_length; $resp_elapsed_time"
}

 

 

hi, the solution works but partly :(. F5 is now happy with the syntax however it is still triggering a 302. I have copied the whole irule here for guidance.

 

#----------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------


when HTTP_REQUEST {
# environment variables
#default, to avoid problems when data-group Emergency_site is not available
set maintenance "false"
set maintenance [class match -value [IP::local_addr] equals "Emergency_site"]
set env "DEV"
set disasterurl "https://xxx
set startpageurl "xxxxx"
set errorpageurl "errorpage"
set pagenotfoundurl "xxx"
set serversslprofile "xxx"
set debug_500_errors "true"

# parameters for request logging to syslog/splunk (and client_address for ip restrictions)
set tcp_start_time [clock clicks -milliseconds]
set req_start_time [clock format [clock seconds] -format "%Y/%m/%d %H:%M:%S"]
set http_host [HTTP::host]
set http_port [TCP::local_port]
set http_uri [HTTP::uri]
set http_url $http_host$http_uri
set http_method [HTTP::method]
set http_version [HTTP::version]
set http_user_agent [HTTP::header "User-Agent"]
set http_content_type [HTTP::header "Content-Type"]
set http_referrer [HTTP::header "Referer"]
set user [HTTP::username]
set virtual_server [LB::server]
set client_address [IP::client_addr]
set vip [IP::local_addr]
set node "F5"
set irule "Irule_redirect"
set node_port "443"
set http_status "302"
set hsl [HSL::open -publisher /Common/syslog_HSL]

# parameters for redirect
# name parameter in datagroup is case sensitive, so use lowercase
set url [string tolower [getfield [HTTP::host] : 1][HTTP::uri]]
set url_path [string tolower [getfield [HTTP::host] : 1][HTTP::path]]

set redirect_value_contains [class match -value $url_path contains https_redirects_list_contains]
set redirect_name_contains [class match -name $url_path contains https_redirects_list_contains]
set redirect_value_equals [class match -value $url_path equals https_redirects_list_equals]
set redirect_name_equals [class match -name $url_path equals https_redirects_list_equals]
set redirect_value_begins [class match -value $url_path starts_with https_redirects_list_begins]
set redirect_name_begins [class match -name $url_path starts_with https_redirects_list_begins]

set dest_url ""
set sub_uri ""
# set logic control flag variable (0 means not yet re-written)
set uri_rewritten 0

# parameters for proxy
set static::uri [string tolower [HTTP::uri]]
set value [class match -value [string tolower [HTTP::uri]] starts_with [getfield [HTTP::host] : 1]_uris]

#----------------------------------------------------------------------------------------------------
# Maintenance page: Change the "maintenance" variable to "true" to enable the redirect.
if { $maintenance equals "true" } {
# check is datagroup with allowed IP's exists
if {! [class exists emergengy_site_allowed_ip]} {
log local0.notice "Data group emergengy_site_allowed_ip not found."
#set hsl [HSL::open -proto TCP -pool POOL-P-INT-OTH041-T601]

# Irule Error 009
HSL::send $hsl "<190>,f5_irule=Splunk-iRule-FAILED,irule_error=009,env=$env,message_type=\"notice\", message=\"Data group emergengy_site_allowed_ip not found.\"\r\n"
}
elseif {![class match $client_address equals emergengy_site_allowed_ip ]} {
# IP not found, request redirected to emergency Site
# Log http redirect to syslog(splunk)
set uri_rewritten 1
set irule "Irule_disaster_redirect"
if { [HTTP::header Content-Length] > 0 } then {
set req_length [HTTP::header "Content-Length"]
}
else {
set req_length 0
}
set res_start_time [clock format [clock seconds] -format "%Y/%m/%d %H:%M:%S"]
set req_elapsed_time [expr {[clock clicks -milliseconds] - $tcp_start_time}]
if { [HTTP::header Content-Length] > 0 } then {
set res_length [HTTP::header "Content-Length"]
}
else {
set res_length 0
}
#set hsl [HSL::open -proto TCP -pool POOL-P-INT-OTH041-T601]


HTTP::redirect $disasterurl
HSL::send $hsl "<190>,f5_irule=Splunk-iRule-HTTP,env=$env,src_ip=$client_address,vip=$vip,irule=$irule,http_method=$http_method,http_host=$http_host,http_port=$http_port,http_dest=$dest_url,http_uri=$http_uri,http_url=$http_url,http_version=$http_version,http_user_agent=\"$http_user_agent\",http_content_type=$http_content_type,http_referrer=\"$http_referrer\",req_start_time=$req_start_time,virtual_server=\"$virtual_server\",bytes_in=$req_length,res_start_time=$res_start_time,node=$node,node_port=$node_port,http_status=$http_status,req_elapsed_time=$req_elapsed_time,bytes_out=$res_length\r\n"
return
}
}
#----------------------------------------------------------------------------------------------------
# disable ASM on error page to avoid endless loop
if {[string tolower [HTTP::path]] equals "/cia/identitystore.web.loginpages/main/error"} {
ASM::disable
}
else {
ASM::enable /Common/asm_iso_auth.sdworx.com
}
#----------------------------------------------------------------------------------------------------
# lookup in datagourp for redirection configurations, parsing urls and build destination url and redirect
# name parameter in datagroup is case sensitive, so use lowercase
# the last char in value determine the type or redirect:
# no special character --> all urls CONTAINING redirect_name will be redirect to redirect_value
# * dynamic redirect, --> all urls CONTAINING redirect_name will be redirect to redirect_value + a part of the incomming URL (destination = value + (Org. url - name)

if { $uri_rewritten equals 0 } {
if { [catch {
if { $redirect_value_equals ne "" } {
# specific redirect found
#set dest_url [string map [list "*" ""] $redirect_value_equals]
set dest_url $redirect_value_equals
} else {
if { $redirect_value_begins ne "" } {
# Begins with redirect found
set dest_url [string map [list "*" ""] $redirect_value_begins]
if {$redirect_value_begins ends_with "*" }{
set sub_uri [string map [list $redirect_name_begins ""] $url]
append dest_url $sub_uri
}
} else {
# generic redirect
if { $redirect_value_contains ne "" } {
set dest_url [string map [list "*" ""] $redirect_value_contains]
if {$redirect_value_contains ends_with "*" }{
set sub_uri [string map [list $redirect_name_contains ""] $url]
append dest_url $sub_uri
}
}
}
}
if { $dest_url ne "" } {
set dest_url "https://$dest_url"
set uri_rewritten 1
}
# Log http redirect to syslog(splunk)
if { $uri_rewritten equals 1 } {
set res_start_time [clock format [clock seconds] -format "%Y/%m/%d %H:%M:%S"]
set req_elapsed_time [expr {[clock clicks -milliseconds] - $tcp_start_time}]
if { [HTTP::header Content-Length] > 0 } then {
set res_length [HTTP::header "Content-Length"]
}
else {
set res_length 0
}
#set hsl [HSL::open -proto TCP -pool POOL-P-INT-OTH041-T601]


#actual redirect
HTTP::redirect $dest_url
HSL::send $hsl "<190>,f5_irule=Splunk-iRule-HTTP,env=$env,src_ip=$client_address,vip=$vip,irule=$irule,http_method=$http_method,http_host=$http_host,http_port=$http_port,http_dest=$dest_url,http_uri=$http_uri,http_url=$http_url,http_version=$http_version,http_user_agent=\"$http_user_agent\",http_content_type=$http_content_type,http_referrer=\"$http_referrer\",req_start_time=$req_start_time,virtual_server=\"$virtual_server\",bytes_in=$req_length,res_start_time=$res_start_time,node=$node,node_port=$node_port,http_status=$http_status,req_elapsed_time=$req_elapsed_time,bytes_out=$res_length\r\n"
}
}]}
{
# error catch to syslog(splunk)
log local0.warn "redirection-failed: from: [IP::remote_addr] for request: [HTTP::host][HTTP::uri]"
#set hsl [HSL::open -proto TCP -pool POOL-P-INT-OTH041-T601]

# Irule Error 008
HSL::send $hsl "<190>,f5_irule=Splunk-iRule-FAILED,irule_error=008,env=$env,message_type=\"warn\", message=\"redirection-failed: from: [IP::remote_addr] for request: [HTTP::host][HTTP::uri]\"\r\n"
}
}
#----------------------------------------------------------------------------------------------------
# Determine if sticky load balancing should be used or not based on the incoming uri
# update by Joachim Hamers: for the new design with loginpages:
# First IP in x-forwarde-for list is always the ip of the client, x-forwarded-for header is enabled on the VIP

if { $static::uri contains "/idhub" }{
#log local0.notice "IDHUB - X-Forwarded-For = [HTTP::header X-Forwarded-For] | remote = [IP::remote_addr]"
#log local0.notice "IDHUB - 1st value X-.. = [lindex [ split [lindex [HTTP::header values X-Forwarded-For] 0] "," ] 0]"
if { [HTTP::header exists "X-Forwarded-For"] }{
persist uie [lindex [ split [lindex [HTTP::header values X-Forwarded-For] 0] "," ] 0]
}
else {
persist source_addr 36000
log local0.notice "IDHUB - X-Forwarded-For header not found (ERROR) "
}
}
#----------------------------------------------------------------------------------------------------
# Only internal content / accessable by internal ip's
if { $uri_rewritten equals 0 } {
#log local0.warn "redirection-onlyInternal: from: [IP::remote_addr] for request: [HTTP::host][HTTP::uri][IP::client_addr]"
if {[class match [string tolower [HTTP::uri]] contains listInternalURLs]} {
if {![class match [IP::client_addr] equals listInternalIPs]} {
set uri_rewritten 1
set irule "Irule_redirection-onlyInternal"
set res_start_time [clock format [clock seconds] -format "%Y/%m/%d %H:%M:%S"]
set req_elapsed_time [expr {[clock clicks -milliseconds] - $tcp_start_time}]

if { [HTTP::header Content-Length] > 0 } then {
set res_length [HTTP::header "Content-Length"]
}
else {
set res_length 0
}
#set hsl [HSL::open -proto TCP -pool POOL-P-INT-OTH041-T601]


HTTP::redirect "$errorpageurl?Code=notAllowed"
HSL::send $hsl "<190>,f5_irule=Splunk-iRule-HTTP,env=$env,src_ip=$client_address,vip=$vip,irule=$irule,http_method=$http_method,http_host=$http_host,http_port=$http_port,http_dest=$dest_url,http_uri=$http_uri,http_url=$http_url,http_version=$http_version,http_user_agent=\"$http_user_agent\",http_content_type=$http_content_type,http_referrer=\"$http_referrer\",req_start_time=$req_start_time,virtual_server=\"$virtual_server\",bytes_in=$req_length,res_start_time=$res_start_time,node=$node,node_port=$node_port,http_status=$http_status,req_elapsed_time=$req_elapsed_time,bytes_out=$res_length\r\n"
}
}
}

#----------------------------------------------------------------------------------------------------
# search server pool in datagroup based on uri
if { $uri_rewritten equals 0 } {
if { $static::uri equals "" || $static::uri equals "/" }{
HTTP::redirect $startpageurl
set uri_rewritten 1
}
else {
if { $value ne "" } {
if { [catch { pool $value } ] } {
log local0.warn "uri-pool-selection-failed: from: [IP::remote_addr] for request: [HTTP::host][HTTP::uri] pool: $value"
#set hsl [HSL::open -proto TCP -pool POOL-P-INT-OTH041-T601]

# Irule Error 001
HSL::send $hsl "<190>,f5_irule=Splunk-iRule-FAILED,irule_error=001,env=$env,message_type=\"warn\", message=\"uri-pool-selection-failed: from: [IP::remote_addr] for request: [HTTP::host][HTTP::uri] pool: $value\"\r\n"
HTTP::redirect "$errorpageurl?Code=uripoolselectionfailed"
set uri_rewritten 1
}
} else {
log local0.notice "uri-pool-lookup-failed: from: [IP::remote_addr] for request: [HTTP::host][HTTP::uri]"
#set hsl [HSL::open -proto TCP -pool POOL-P-INT-OTH041-T601]

# Irule Error 002
HSL::send $hsl "<190>,f5_irule=Splunk-iRule-FAILED,irule_error=002,env=$env,message_type=\"notice\", message=\"uri-pool-lookup-failed: from: [IP::remote_addr] for request: [HTTP::host][HTTP::uri]\"\r\n"
HTTP::redirect "$pagenotfoundurl"
set uri_rewritten 1
}
}
}
unset value
}
#****************************************************************************************************
when HTTP_RESPONSE {
set hsl [HSL::open -publisher /Common/syslog_HSL]
# Catch backend errors and redirect to central page
if { $uri_rewritten equals 0 } {
if { ([HTTP::status]=="500") && \
([HTTP::header Content-Type] contains "application/json" || \
[HTTP::header Content-Type] contains "application/xml" || \
[HTTP::header Content-Type] contains "application/problem+json") } {
set irule "Irule_Catch_500"
set http_status [HTTP::status]
#set content ""
set res_start_time [clock format [clock seconds] -format "%Y/%m/%d %H:%M:%S"]
set req_elapsed_time [expr {[clock clicks -milliseconds] - $tcp_start_time}]
# Get the content length so we can request the data to be
# processed in the HTTP_RESPONSE_DATA event.
if { [HTTP::header exists "Content-Length"] } {
set req_length [HTTP::header "Content-Length"]
} else {
set req_length 0
}

# dump HTML response to log if parameter debug_500_errors is true
# content_length of 0 indicates chunked data (of unknown size)
#set hsl [HSL::open -proto TCP -pool POOL-P-INT-OTH041-T601]

if { $debug_500_errors equals "true" } {
if { $req_length > 0 && $req_length < 1048577 } {
set collect_length $req_length
} else {
set collect_length 1048576
}
if { $req_length > 0 } {
HTTP::collect $req_length
set content [b64encode [string map {"\n" "" "," "" "=" "" "\"" ""} [HTTP::payload]]]
}
HSL::send $hsl "<190>,f5_irule=Splunk-iRule-HTTP,env=$env,src_ip=$client_address,vip=$vip,irule=$irule,http_method=$http_method,http_host=$http_host,http_port=$http_port,http_dest=$dest_url,http_uri=$http_uri,http_url=$http_url,http_version=$http_version,http_user_agent=\"$http_user_agent\",http_content_type=$http_content_type,http_referrer=\"$http_referrer\",req_start_time=$req_start_time,virtual_server=\"$virtual_server\",bytes_in=$req_length,res_start_time=$res_start_time,node=$node,node_port=$node_port,http_status=$http_status,req_elapsed_time=$req_elapsed_time,bytes_out=$res_length,content=$content\r\n"
} else {
HSL::send $hsl "<190>,f5_irule=Splunk-iRule-HTTP,env=$env,src_ip=$client_address,vip=$vip,irule=$irule,http_method=$http_method,http_host=$http_host,http_port=$http_port,http_dest=$dest_url,http_uri=$http_uri,http_url=$http_url,http_version=$http_version,http_user_agent=\"$http_user_agent\",http_content_type=$http_content_type,http_referrer=\"$http_referrer\",req_start_time=$req_start_time,virtual_server=\"$virtual_server\",bytes_in=$req_length,res_start_time=$res_start_time,node=$node,node_port=$node_port,http_status=$http_status,req_elapsed_time=$req_elapsed_time,bytes_out=$res_length\r\n"
}
HTTP::redirect "$errorpageurl?HttpStatusCode=[HTTP::status]&Code=BackendHTTPCodeError"
set uri_rewritten 1
return
}
if { ([HTTP::status]== "404") && \
([HTTP::header Content-Type] contains "application/json" || \
[HTTP::header Content-Type] contains "application/xml" || \
[HTTP::header Content-Type] contains "application/problem+json") } {
set irule "Irule_Catch_404"
set http_status [HTTP::status]
set res_start_time [clock format [clock seconds] -format "%Y/%m/%d %H:%M:%S"]
set req_elapsed_time [expr {[clock clicks -milliseconds] - $tcp_start_time}]
if { [HTTP::header exists "Content-Length"] } {
set req_length [HTTP::header "Content-Length"]
} else {
set req_length 0
}
#set hsl [HSL::open -proto TCP -pool POOL-P-INT-OTH041-T601]

HSL::send $hsl "<190>,f5_irule=Splunk-iRule-HTTP,env=$env,src_ip=$client_address,vip=$vip,irule=$irule,http_method=$http_method,http_host=$http_host,http_port=$http_port,http_dest=$dest_url,http_uri=$http_uri,http_url=$http_url,http_version=$http_version,http_user_agent=\"$http_user_agent\",http_content_type=$http_content_type,http_referrer=\"$http_referrer\",req_start_time=$req_start_time,virtual_server=\"$virtual_server\",bytes_in=$req_length,res_start_time=$res_start_time,node=$node,node_port=$node_port,http_status=$http_status,req_elapsed_time=$req_elapsed_time,bytes_out=$res_length\r\n"
HTTP::redirect $pagenotfoundurl
set uri_rewritten 1
return
}
}

#----------------------------------------------------------------------------------------------------
# Remove all instances of the Server header
HTTP::header remove Server
# Remove all headers starting with x-
foreach header_name [HTTP::header names] {
if {[string match -nocase x-* $header_name]}{
HTTP::header remove $header_name
}
}

Hi @krisnaseechurn, the HTTP::redirect command is used a couple of times in your iRule.

It´s best practice, to use a "return" command afterwards and perhaps an "event disable" command to prevent the iRule from further execution.

Personally I´m trying to avoid the HTTP::redirect. Instead I prefer to use HTTP::respond because it´s providing very granular control about the exact status code (maybe you prefer a 301 instead of 302?). It also allows to add a Connection Close header. Along with an "event disable" command followed by a "return" you will definitely avoid further execution of the iRule event where the command was fired.

For debugging it would help to force an unwanted redirect and monitor the /var/log/ltm for log entries and TCL errors/warnings:

tail -f /var/log/ltm

 

thanks for all the input..

the issue was it was missing an !

if { !([HTTP::status]=="500") && \