Forum Discussion

Caio_178191's avatar
Caio_178191
Icon for Nimbostratus rankNimbostratus
Dec 15, 2015

iRule error after upgrade version (Operation not supported. Multiple redirect/respond invocations not allowed)

Hi, good afternoon.

After upgrade a BIG IP OS from 10.2.4 to 11.5.1 HF10, I started to see a lot of errors in LTM log. I have many iRules in my system and many of those iRules are givin me "Operation not supported. Multiple redirect/respond invocations not allowed" errors.

I have here a simple iRule like

when HTTP_REQUEST {
   if { [string tolower [HTTP::path]] equals "/something.txt" } {
      HTTP::respond 200 content "User-agent: * \nDisallow: /somretyhing.pe \nAllow: /"
      return
   }
}

And this irule is givin the error I said. And many other are like these and is giving the operation not supported error.

Please help, someone see that before?

Thanks.

  • Hi Ciao,

    this error would happen if a previous rule had already responded the request and you try to respond a second time to the very same request. The return command unfortenately doesn't stop the processing of following iRules...

    You may either combine those rules into a single one and then

    return
    the script after each
    [HTTP::respond]
    ...

    when HTTP_REQUEST {
       if { [string tolower [HTTP::path]] equals "/something.txt" } {
          HTTP::respond 200 content "User-agent: * \nDisallow: /somretyhing.pe \nAllow: /"
          return
       }
       if { [string tolower [HTTP::path]] equals "/somethingother.txt" } {
          HTTP::respond 200 content "User-agent: * \nDisallow: /somretyhing.pe \nAllow: /"
          return
       }
    }
    

    ... or you may inform the later iRules that the request is already responded...

    when HTTP_REQUEST {
       set already_responded 0
       if { [string tolower [HTTP::path]] equals "/something.txt" } {
          HTTP::respond 200 content "User-agent: * \nDisallow: /somretyhing.pe \nAllow: /"
          set already_responded 1
          return
       }
    }
    when HTTP_REQUEST {
       if { $already_responded } {
            do nothing
       } else {
           if { [string tolower [HTTP::path]] equals "/somethingother.txt" } {
              HTTP::respond 200 content "User-agent: * \nDisallow: /somretyhing.pe \nAllow: /"
              return
           }
       }
    }
    

    Note: Keep in mind to trigger a

    set already_responded 0
    in the first iRule to initialize/reset the variable.

    A third option would be to see if a response is already send to the client by trying to minipulate the REQUEST or RESPONSE headers and [catch] the error which would happen if a response is already send. But this could have a certain performance impact.

    when HTTP_REQUEST {
       if { [catch {HTTP::payload replace 0 0 {}}] } then { 
            do nothing
       } else {
           if { [string tolower [HTTP::path]] equals "/something.txt" } {
              HTTP::respond 200 content "User-agent: * \nDisallow: /somretyhing.pe \nAllow: /"
              return
           }
       }
    }
    
    when HTTP_REQUEST {
       if { [catch {HTTP::payload replace 0 0 {}}] } then { 
            do nothing
       } else {
           if { [string tolower [HTTP::path]] equals "/somethingother.txt" } {
              HTTP::respond 200 content "User-agent: * \nDisallow: /somretyhing.pe \nAllow: /"
              return
           }
       }
    }
    

    Cheers, Kai

  • Assuming all your iRules are the same as your sample, replace

    return
    with
    event disable
    function in all iRules that invoke redirects or responses. The return function is not needed here. The event disable function should be called after each redirect or response statement, unless you merge the iRules together so that this particular TCL error can no longer occur. By doing so, you may also want to look into iRule execution priorities to make sure no important functionality is superseded.

    https://devcentral.f5.com/questions/stop-processing-irule-s-if-condition-is-met

    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP
      Hey Hannes, as far as I know "event disable" is persistent to the TCP connection. So it would cause keep-alive'ed connections to not trigger the HTTP_REQUEST events on the very next request. Isn't it? Cheers, Kai
    • Hannes_Rapp's avatar
      Hannes_Rapp
      Icon for Nimbostratus rankNimbostratus
      Indeed, but if needed, you can also add a 'TCP::close' function after the 'event disable' function, to eliminate any possibility of problems with long sessions. A new TCP handshake (and possible SSL handshake) after each F5-initiated HTTP response or redirect should not be a performance hazard. You can achieve the same by appending a 'Connection Close' flag with your HTTP::respond functions. Yet another possibility is conditionally re-enabling the HTTP_REQUEST event, but i'd just prefer closing down on the TCP level for simplicity.
    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP
      Hi Hannes, thanks for confirming. So nothing has changed since then... :-( BTW: Did you already tried to use LTM Policies to reenable events on every single request? Could be an option now, or isn't it? Cheers, Kai
  • Assuming all your iRules are the same as your sample, replace

    return
    with
    event disable
    function in all iRules that invoke redirects or responses. The return function is not needed here. The event disable function should be called after each redirect or response statement, unless you merge the iRules together so that this particular TCL error can no longer occur. By doing so, you may also want to look into iRule execution priorities to make sure no important functionality is superseded.

    https://devcentral.f5.com/questions/stop-processing-irule-s-if-condition-is-met

    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP
      Hey Hannes, as far as I know "event disable" is persistent to the TCP connection. So it would cause keep-alive'ed connections to not trigger the HTTP_REQUEST events on the very next request. Isn't it? Cheers, Kai
    • Hannes_Rapp_162's avatar
      Hannes_Rapp_162
      Icon for Nacreous rankNacreous
      Indeed, but if needed, you can also add a 'TCP::close' function after the 'event disable' function, to eliminate any possibility of problems with long sessions. A new TCP handshake (and possible SSL handshake) after each F5-initiated HTTP response or redirect should not be a performance hazard. You can achieve the same by appending a 'Connection Close' flag with your HTTP::respond functions. Yet another possibility is conditionally re-enabling the HTTP_REQUEST event, but i'd just prefer closing down on the TCP level for simplicity.
    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP
      Hi Hannes, thanks for confirming. So nothing has changed since then... :-( BTW: Did you already tried to use LTM Policies to reenable events on every single request? Could be an option now, or isn't it? Cheers, Kai
  • Thank you all for the answers. I will do tests here and when have answers I will let u know.