Forum Discussion
Can't use non-numeric string as operand of "&&" in rule
Hello. When this irule runs the following error occurs:
/Common/SSL_Test - can't use non-numeric string as operand of "&&" while executing "if { $renegtried == 0 and [SSL::cert count] == 0 and ( ([HTTP::uri] matches_regex {^/test1$}) or ([HTTP::uri] matches_reg..."
when HTTP_REQUEST { set uri [string tolower [HTTP::uri] ] /_hst name and ?_hst=1 parameter triggers client cert renegotiation if { $renegtried == 0 and [SSL::cert count] == 0 and ( ([HTTP::uri] matches_regex {^/test1$}) or ([HTTP::uri] matches_regex {^/prob$}) or ([HTTP::uri] matches_regex {^/Register$}) ) } {
How I can fix it? Thank you.
10 Replies
- Stanislas_Piro2
Cumulonimbus
Hi,
First, Regex is useless in your irule. it will generate performance issues.
- use ([HTTP::uri] starts_with /test1) instead of ([HTTP::uri] matches_regex {^/test1})
- use ([HTTP::uri] ends_with /test1) instead of ([HTTP::uri] matches_regex {/test1$})
- use ([HTTP::uri] equals /test1) instead of ([HTTP::uri] matches_regex {^/test1$})
Your issue is your 2 first conditions do not have parenthesis.
($renegtried == 0) and ([SSL::cert count] == 0)and you can replace ($renegtried == 0) by !($renegtried)
- Demonio_21719
Nimbostratus
Thanks for your help. I've applied but does not work:
- when HTTP_REQUEST {
- set uri [string tolower [HTTP::uri] ]
- /_hst name and ?_hst=1 parameter triggers client cert renegotiation
- if { !($renegtried) and ([SSL::cert count] == 0)
- and (([HTTP::uri] equals "/extern/test.jsp") or ([HTTP::uri] equal "/SO/services/dat") or * ([HTTP::uri] equal "/test/services/Tasacion") or [(HTTP::uri] equal "/Ex/services/pay"))
- } {
- log local0. "[IP::client_addr]:[TCP::client_port]: A log entry"
- HTTP::collect
- SSL::cert mode request
- SSL::renegotiate
- }
- }
- The error is this:
- :01070151:3: Rule [/Common/SSL_Test] error: /Common/Common/SSL_Test:12: error: [parse error: PARSE syntax 465 {syntax error in expression "!($renegtried)and ([SSL::cert count] == 0)and ...": variable references require preceding $}][{!($renegtried)and ([SSL::cert count] == 0)and (([HTTP::uri] equals "/extern/test.jsp") or ([HTTP::uri] equal "/SO/services/dat") or ([HTTP::uri] equal "/test/services/Tasacion") or [(HTTP::uri] equal "/Ex/services/pay"))}]
- VernonWells
Employee
Here is your code formatted:
when HTTP_REQUEST { set uri [string tolower [HTTP::uri] ] /_hst name and ?_hst=1 parameter triggers client cert renegotiation if { !($renegtried) and ([SSL::cert count] == 0) and (([HTTP::uri] equals "/extern/test.jsp") or ([HTTP::uri] equal "/SO/services/dat") or ([HTTP::uri] equal "/test/services/Tasacion") or [(HTTP::uri] equal "/Ex/services/pay")) } { log local0. "[IP::client_addr]:[TCP::client_port]: A log entry" HTTP::collect SSL::cert mode request SSL::renegotiate } }You have some oddly placed characters (for example, "[(" and sometimes you put "equal" rather than "equals"). In any case, a switch for equality will be easier to read:
when HTTP_REQUEST { switch [HTTP::uri] { "/extern/test.jsp" - "/SO/services/dat" - "/Ex/services/pay" { if { !$renegtried && [SSL::cert count] == 0 } { log local0. "[IP::client_addr]:[TCP::client_port]: A log entry" HTTP::collect SSL::cert mode request SSL::renegotiate } } } }Note that I removed the string tolower. Ordinarily, URI paths are case-sensitive (assuming your server and filesystem are) so the conversion is of no real value. Indeed, you perform the conversion, assign the value to $uri then never reference that variable. If you really do care, you can simply substitute that back in.
- Demonio_21719
Nimbostratus
* tHANK YOU!! * And if I want to add any condition in the HTTP_REQUEST?, for example (SOME "ELSE IF and * ELSE"): * Do I have to put an if before the switch? * For example:
- when HTTP_REQUEST {
- switch [HTTP::uri] {
- "/extern/test.jsp" -
- "/SO/services/dat" -
- "/Ex/services/pay" {
- if { !$renegtried && [SSL::cert count] == 0 } {
- log local0. "[IP::client_addr]:[TCP::client_port]: A log entry"
- HTTP::collect
- SSL::cert mode request
- SSL::renegotiate
- pool TEST-BACKUP <---- PRIORITY POOL
- }
- }
- }
- }
TO ADD:
- } elseif {
- ([HTTP::host] equals www.test.es } {
- pool SECOND_POOL_SSL <---- SECOND POOL
- SSL::enable serverside
- log local0. "WITH SECOND POOL"
- } else {
- pool THIRD-POOL-SSL <---- THIRD POOL
- SSL::disable serverside
- log local0. "WITH THIRD POOL POOL"
- }
- VernonWells
Employee
Depends on to what the elseif is attached. Does it apply only when one of the three URI paths are matched? If not, you could place a return in the existing match clause, then put your if...else outside the switch, like so:
when HTTP_REQUEST { switch [HTTP::uri] { "/extern/test.jsp" - "/SO/services/dat" - "/Ex/services/pay" { if { !$renegtried && [SSL::cert count] == 0 } { log local0. "[IP::client_addr]:[TCP::client_port]: A log entry" HTTP::collect SSL::cert mode request SSL::renegotiate return } } } end up here if none of the three URI paths above match, or if one of them does match but either $renegtried or SSL::cert count != 0 if { [string tolower [HTTP::host]] equals "www.test.es" } { pool SECOND_POOL_SSL SSL::enable serverside log local0. "WITH SECOND POOL" } else { pool THIRD-POOL-SSL SSL::disable serverside log local0. "WITH THIRD POOL POOL" } }For test of HTTP::host using string tolower is important, because the client may submit the Host: header in any case, and DNS is case indifferent.
- Demonio_21719
Nimbostratus
Hello, Now, it works correctly, but the elseif and else, returns to give the error "can not use non-numeric string as operand of" && "Definitely, how it could be better?
when CLIENT_ACCEPTED { set collecting 0 set renegtried 0 set default_pool [LB::server pool] } when HTTP_REQUEST { set uri [string tolower [HTTP::uri] ] /_hst name and ?_hst=1 parameter triggers client cert renegotiation switch [HTTP::uri] { "/extern/test.jsp" - "/SO/services/dat" - "/Ex/services/pay" { if { !$renegtried && [SSL::cert count] == 0 } { log local0. "[IP::client_addr]:[TCP::client_port]: A log entry" Collecting means buffering the request. The collection goes on until SSL::renegotiate occurs, which happens after the HTTP request has been received. The maximum data buffered by collect is 1-4 MB. HTTP::collect set collecting 1 SSL::cert mode request SSL::renegotiate pool FIRST_POOL_SSL SSL::enable serverside log local0. "WITH FIRST POOL" return } } } if { $uri equals "/extern/test.jsp" } { pool FIRST_POOL_SSL SSL::enable serverside log local0. "WITH FIRST POOL" } elseif { ([string tolower [HTTP::host]] eq "www.test.es") && ($uri eq "/abc") }{ HTTP::redirect "https://www.test.es/test1/" } elseif { ([string tolower [HTTP::host]] eq "www.test.es") && ($uri contains "/") && ($uri) }{ HTTP::redirect "https://www.test.es[HTTP::uri]" } else { pool $default_pool SSL::disable serverside log local0. "WITH SECOND POOL" } }- Stanislas_Piro2
Cumulonimbus
Hi, I think the issue is : && ($uri)
- VernonWells
Employee
It almost certainly is what @stanislas pointed out.
As an extended note, however, since your are testing the URI path in the additional branches, it makes sense to fold those into the switch, as well. I don't really understand the last branch because a URI path will always contain a slash (/), so that conditional match is always true. Therefore, I pushed it to the switch default condition.
when CLIENT_ACCEPTED { set collecting 0 set renegtried 0 } when HTTP_REQUEST { set uri [string tolower [HTTP::uri] ] /_hst name and ?_hst=1 parameter triggers client cert renegotiation switch [HTTP::uri] { "/extern/test.jsp" - "/SO/services/dat" - "/Ex/services/pay" { if { !$renegtried && [SSL::cert count] == 0 } { log local0. "[IP::client_addr]:[TCP::client_port]: A log entry" Collecting means buffering the request. The collection goes on until SSL::renegotiate occurs, which happens after the HTTP request has been received. The maximum data buffered by collect is 1-4 MB. HTTP::collect set collecting 1 SSL::cert mode request SSL::renegotiate pool FIRST_POOL_SSL SSL::enable serverside log local0. "WITH FIRST POOL" } "/extern/test.jsp" { pool FIRST_POOL_SSL SSL::enable serverside log local0. "WITH FIRST POOL" } "/abc" { if { [string tolower [HTTP::host]] eq "www.test.es"] } { HTTP::redirect "https://www.test.es/test1/" } } default { if { [string tolower [HTTP::host]] eq "www.test.es" } { HTTP::redirect "https://www.test.es[HTTP::uri]" } else { SSL::disable serverside log local0. "WITH SECOND POOL" } } } } }Since everything is in the switch now, there is no need for the return in the first condition.
Incidentally, in the last condition, you set the pool to LB::server pool. There is no reason to do this. If you don't invoke pool in your iRule, that is already the pool that will be selected. So, I removed that.
Also, I assume this is not the entire iRule. When you use HTTP::collect in HTTP_REQUEST, if you don't attach a listener to the HTTP_REQUEST_DATA event and invoke HTTP::release somewhere in there, the iRule will stall (and, more importantly, there would be no value in calling HTTP::collect unless you do something with the data).
- Demonio_21719
Nimbostratus
Thank you very much for your help. Good morning, we have implemented the irule to HTTP_REQUEST, and works perfectly. The problem appears many errors like this:
TCL error: /Common/Common/SSL_Test:12 - command returned bad code: 24 while executing " /_hst name and ?_hst=1 parameter triggers client cert renegotiation switch [HTTP::uri] { "/extern/test.jsp" - "/SO/..."
It could be a bug in version 11.6.0 HF5?
Gretting
- VernonWells
Employee
Perhaps, but Tcl is finicky about where comments end up. Have you tried removing the comment line
/_hst name and ?_hst=1 parameter triggers client cert renegotiationto see if the errors go away?
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com