Forum Discussion

uni's avatar
uni
Icon for Altostratus rankAltostratus
Oct 16, 2006

Stop event processing for multiple rules

I have virtuals defined with two rules: one rule which is common to all, and one customised for each virtual. All the rule processing is done within the HTTP_REQUEST event.

Can anyone suggest a simple way of stopping the HTTP_REQUEST event from firing in the second rule if certain conditions are met within the first rule's HTTP_REQUEST event?

I've tried the
return
statement, but this goes on to process the second rule.

9 Replies

  • Hi Stephen,

     

     

    You can use 'event disable' to stop the processing of that event further. You can use 'event disable all' to stop all further processing after the current event.

     

     

    If you have two rules and call 'event HTTP_REQUEST disable' in the first rule's HTTP_REQUEST event, the first rule's HTTP_REQUEST will be triggered while the second rule's HTTP_REQUEST event wouldn't be triggered.

     

     

    Aaron
  • uni's avatar
    uni
    Icon for Altostratus rankAltostratus
    Thanks hoolio. This is pretty much the answer I was looking for.

     

     

    The doco says the event command disables the event for the current connection. In the case of the HTTP_REQUEST event, though, there may be multiple requests on the one connection, so requests issued on the connection after the event is disabled will not be processed by the rule event.

     

     

    Can you see a way around this?
  • That's a good point...

    I tested this just to make sure and indeed, when you disable the event in the first rule, it's not triggered again for the second rule or any other HTTP requests over the same TCP connection:

    
    rule log_events_rule_1 {
       when CLIENT_ACCEPTED {
       log local0. "[clock clicks -milliseconds]"
    }
    when HTTP_REQUEST {
       event HTTP_REQUEST disable
       log local0. "[clock clicks -milliseconds]"
    }
    when HTTP_RESPONSE {
       log local0. "[clock clicks -milliseconds]"
    }
    when CLIENT_CLOSED {
       log local0. "[clock clicks -milliseconds]"
    }
    }

    
    rule log_events_rule_2 {
       when CLIENT_ACCEPTED {
       log local0. "[clock clicks -milliseconds]"
    }
    when HTTP_REQUEST {
       log local0. "[clock clicks -milliseconds]"
    }
    when HTTP_RESPONSE {
       log local0. "[clock clicks -milliseconds]"
    }
    when CLIENT_CLOSED {
       log local0. "[clock clicks -milliseconds]"
    }
    }

    I made ten requests using CURL, which re-uses the same TCP connection for multiple HTTP requests:

    curl http://http_vip/test[0-9]

    Checked the logging for the rules and it shows the HTTP_REQUEST event is only triggered for the first rule and only once per TCP connection:

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276803

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276803

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276803

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276804

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276804

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276808

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276808

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276812

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276812

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276816

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276816

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276819

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276819

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276822

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276822

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276826

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276826

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276829

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276829

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276832

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276832

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276836

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276836

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_1 : 1524276838

    Oct 18 10:57:26 tmm tmm[1234]: Rule log_events_rule_2 : 1524276838

    So I think the simplest workaround is to combine the two rules into one rule.

    I suppose you could try something fancy with setting a global variable in the first rule that the second rule checks. But I think it might get complicated trying to differentiate which TCP connection the variable is referencing. Or perhaps you could use the session table.

    Does anyone else have suggestions on this?

    Thanks,

    Aaron
  • One other quick note:

    Using return stops further processing of commands in the current event in the current rule:

    
    when HTTP_REQUEST {
       log local0. "hit HTTP_REQUEST event"
       return
       log local0. "This will never be triggered!"
    }
    when HTTP_RESPONSE {
       log local0. "hit HTTP_RESPONSE event"
    }
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Hi Stephen --

     

     

    You can issue a conditional TCP::close (at the end of the response in the 2nd rule) to prevent subsequent requests on that connection, or return / event disable (in the relevant events) to prevent processing of all or specific parts of the subsequent iRules.

     

     

    Either method of connection control would use the following approach: If some specified condition occurs within the first rule, set a variable as a flag in HTTP_REQUEST in the first rule where you are currently using "return" indicating that the condition was seen, then in the second rule, use the value of that variable to control whether the return, event disable, or close is processed.

     

     

    HTH

     

    /deb
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Edited above for clarity.

     

     

    Also wanted to say that hoolio's recommendation to combine the rules is F5 Product Development's recommended best practice (whenever possible), rather than configuring multiple rules on the same virtual server, due to the issues stephen is encountering.

     

     

    /deb
  • uni's avatar
    uni
    Icon for Altostratus rankAltostratus
    Thanks Deb and hoolio for your replies.

     

     

    I had pretty much already decided that one rule was better than two. The need to have inter-dependence with flags etc. defeats the purpose of splitting the rules. It was a naive attempt at writing modular rules, but without user defined functions or subroutines that's not really practical.

     

     

    unRuleY, would I need to worry about race conditions, such as when a second request is received on a connection before a response is received to a prior request which had disabled the HTTP_REQUEST event?