Forum Discussion
Undefined Procedure with elseif when using comments
I am having trouble committing the following iRule when adding in comments above the elseif statements. It always interprets the first comment it finds above an elseif statement as the offender.
01070151:3: Rule [/Common/Main_Website_80_Revised] error: /Common/Main_Website_80_Revised:7: error: [undefined procedure: elseif][elseif {[class match [HTTP::host] eq group_80_encrypt]} {
HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
}]
Removing all comments (aside from line 2, that one seems fine) will commit the iRule without any issue. Any idea what might be going on?
when HTTP_REQUEST {
302 redirect to a different URL based on hostname
if {[class match [HTTP::host] eq group_80_host_redirect]} {
HTTP::redirect [class match -value [HTTP::host] eq group_80_host_redirect]
}
302 redirect to enforce HTTPS based on hostname or URI
elseif {[class match [HTTP::host] eq group_80_encrypt]} {
HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
}
Pool selection based on hostname
elseif {[class match [HTTP::host] eq group_80_host_pool]} {
pool [class match -value [HTTP::host] eq group_80_host_pool]
}
Pool selection based on URI
elseif {[class match [HTTP::uri] starts_with group_80_uri_pool]} {
pool [class match -value [HTTP::uri] starts_with group_80_uri_pool]
}
else {
pool Main_80_Pool
}
}
This results from a peculiarity of Tcl. The language doesn't really have built-ins and it doesn't really have blocks. Rather, it has commands and non-interpolated quoted strings. As such,
is a command (just likeif
orsplit
). It is followed by a quoted block (the {}s, in Tcl, are really non-interpolating quoting operators, and not really block delimiters as they are in most languages). The quoted block may then be optionally followed by zero or moreHTTP::headers
literals (each followed by a quoted block) and zero or oneelseif
literals (followed by a quoted block). When a condition is met, the contents of the corresponding quoted block are evaluated.else
Said another way, in Tcl, an
/if
/elseif
set is really a single statement. The statement command iselse
. Theif
andelseif
are just parameters to this command. And because the newlines in the blocks are ignored by the parser (because they are inside of the non-interpolating {} quoting operators), the entire statement is effectively on one line.else
As a side-effect of this, in Tcl you MUST cuddle an
/if
/elseif
block, as in:else
if { ... } { ... } else { ... }
This is not allowed:
if { ... } { ... } else { ... }
However, this trips up most programmers, so iRules (a Tcl dialect) allows non-cuddled
blocks. But if you add a comment between the control elements, this effectively inserts a newline. So, with the comments you have above, the parser "sees" this:if
if { ... } elseif { ... } else { ... }
which it thinks is really three different commands:
,if
andelseif
. Onlyelse
is a command; the others are not (again, they are just parameters of theif
command).if
Okay, so that's really just a long-winded way of saying: you must move those comments inside the squirly braces ({}). 🙂
- VernonWellsEmployee
This results from a peculiarity of Tcl. The language doesn't really have built-ins and it doesn't really have blocks. Rather, it has commands and non-interpolated quoted strings. As such,
is a command (just likeif
orsplit
). It is followed by a quoted block (the {}s, in Tcl, are really non-interpolating quoting operators, and not really block delimiters as they are in most languages). The quoted block may then be optionally followed by zero or moreHTTP::headers
literals (each followed by a quoted block) and zero or oneelseif
literals (followed by a quoted block). When a condition is met, the contents of the corresponding quoted block are evaluated.else
Said another way, in Tcl, an
/if
/elseif
set is really a single statement. The statement command iselse
. Theif
andelseif
are just parameters to this command. And because the newlines in the blocks are ignored by the parser (because they are inside of the non-interpolating {} quoting operators), the entire statement is effectively on one line.else
As a side-effect of this, in Tcl you MUST cuddle an
/if
/elseif
block, as in:else
if { ... } { ... } else { ... }
This is not allowed:
if { ... } { ... } else { ... }
However, this trips up most programmers, so iRules (a Tcl dialect) allows non-cuddled
blocks. But if you add a comment between the control elements, this effectively inserts a newline. So, with the comments you have above, the parser "sees" this:if
if { ... } elseif { ... } else { ... }
which it thinks is really three different commands:
,if
andelseif
. Onlyelse
is a command; the others are not (again, they are just parameters of theif
command).if
Okay, so that's really just a long-winded way of saying: you must move those comments inside the squirly braces ({}). 🙂
- cody8411_186897NimbostratusExcellent explanation. That definitely makes sense now that I understand how the code is interpreted in Tcl. Moved the comments down inside the commands and worked as expected, thank you!
- Vernon_97235Historic F5 Account
This results from a peculiarity of Tcl. The language doesn't really have built-ins and it doesn't really have blocks. Rather, it has commands and non-interpolated quoted strings. As such,
is a command (just likeif
orsplit
). It is followed by a quoted block (the {}s, in Tcl, are really non-interpolating quoting operators, and not really block delimiters as they are in most languages). The quoted block may then be optionally followed by zero or moreHTTP::headers
literals (each followed by a quoted block) and zero or oneelseif
literals (followed by a quoted block). When a condition is met, the contents of the corresponding quoted block are evaluated.else
Said another way, in Tcl, an
/if
/elseif
set is really a single statement. The statement command iselse
. Theif
andelseif
are just parameters to this command. And because the newlines in the blocks are ignored by the parser (because they are inside of the non-interpolating {} quoting operators), the entire statement is effectively on one line.else
As a side-effect of this, in Tcl you MUST cuddle an
/if
/elseif
block, as in:else
if { ... } { ... } else { ... }
This is not allowed:
if { ... } { ... } else { ... }
However, this trips up most programmers, so iRules (a Tcl dialect) allows non-cuddled
blocks. But if you add a comment between the control elements, this effectively inserts a newline. So, with the comments you have above, the parser "sees" this:if
if { ... } elseif { ... } else { ... }
which it thinks is really three different commands:
,if
andelseif
. Onlyelse
is a command; the others are not (again, they are just parameters of theif
command).if
Okay, so that's really just a long-winded way of saying: you must move those comments inside the squirly braces ({}). 🙂
- cody8411_186897NimbostratusExcellent explanation. That definitely makes sense now that I understand how the code is interpreted in Tcl. Moved the comments down inside the commands and worked as expected, thank you!
- Salvador_del_ReHistoric F5 AccountI have the same problema. I insert the comments below and don´t have issues if {[class match [HTTP::host] eq group_80_host_redirect]} { HTTP::redirect [class match -value [HTTP::host] eq group_80_host_redirect] 302 redirect to a different URL based on hostname } elseif {[class match [HTTP::host] eq group_80_encrypt]} { HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] 302 redirect to enforce HTTPS based on hostname or URI }
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