Forum Discussion

spankme_86674's avatar
spankme_86674
Icon for Nimbostratus rankNimbostratus
Nov 23, 2012

Optimizing redirects to avoid TCL error "Multiple redirect/respond invocations"

Hi everyone,

 

I would like to ask for help in finding the reason why following rule (stripped out of confidential data) is causing the error of:

 

 

Fri Nov 23 04:06:03 GMT 2012 err local/tmm3 tmm3[6833] 01220001 TCL error: goRedirects - Operation not supported. Multiple redirect/respond invocations not allowed (line 21) invoked from within "HTTP::respond 301 Location $rdr_target"

 

Fri Nov 23 04:06:04 GMT 2012 err local/tmm3 tmm3[6833] 01220001 TCL error: goRedirects - Operation not supported. Multiple redirect/respond invocations not allowed (line 17) invoked from within "HTTP::respond 301 Location "http://blabla/vod/page/default/home.do""

 

Fri Nov 23 04:06:04 GMT 2012 err local/tmm tmm[6830] 01220001 TCL error: goRedirects - Operation not supported. Multiple redirect/respond invocations not allowed (line 11) invoked from within "HTTP::respond 301 Location $rdr_target"

 

Fri Nov 23 04:07:46 GMT 2012 err local/tmm1 tmm1[6831] 01220001 TCL error: goRedirects - Operation not supported. Multiple redirect/respond invocations not allowed (line 21) invoked from within "HTTP::respond 301 Location $rdr_target"

 

Fri Nov 23 04:08:23 GMT 2012 err local/tmm3 tmm3[6833] 01220001 TCL error: goRedirects - Operation not supported. Multiple redirect/respond invocations not allowed (line 11) invoked from within "HTTP::respond 301 Location "http://blabla[HTTP::uri]""

 

 

The rule:

 

 

when HTTP_REQUEST {

 

log local0. "Found [HTTP::host]"

 

if { [HTTP::path] equals "/" or [HTTP::path] equals "/vod" } {

 

HTTP::path "/vod/"

 

}

 

set rdr_target [class match -value [HTTP::uri] equals some_uri_redirects]

 

if { $rdr_target ne "" } {

 

HTTP::respond 301 Location $rdr_target

 

log local0. "Found match with value = $rdr_target"

 

}

 

if { [HTTP::path] starts_with "/watch" } {

 

HTTP::respond 301 Location "http://blabla/vod/page/default/home.do"

 

}

 

if { [HTTP::host] equals "blabla" } {

 

log local0. "Found [HTTP::host]"

 

set rdr_target [class match -value [HTTP::uri] equals someother_uri_redirects]

 

if { $rdr_target ne "" } {

 

HTTP::respond 301 Location $rdr_target

 

log local0. "Found match with value = $rdr_target for blabla"

 

} else {

 

if { [TCP::local_port] equals "80" } {

 

HTTP::respond 301 Location "http://blabla[HTTP::uri]"

 

} else {

 

HTTP::redirect "https://blabla[HTTP::uri]"

 

}

 

}

 

}

 

}

 

 

Thanks in advance!

 

S.

 

19 Replies

  • Well, apparently it cant go to Data Group for the reason I've mentioned: in iRule it has a regexp form, where it triggers for anything that starts with '/watch', like '/watch', '/watch/' but also '/watch/anything' and so on. It seems that in data group it can only match exactly that, what's used as a string, unless there is a trick to turn it into the same regexp as in iRule.
  • The string name or value must match exactly only with what you are comparing it to. So using 'class match [HTTP::uri] starts with "/watch"' would match /watch and /watch/this. As long as /watch is matched it's all good. The operator used and the variable are what matter. Does that make sense?
  • Yes, it perfectly makes sense and I hoped it works that way, but unfortunately my tests are showing that it isnt working like that. What I did was:

     

    1) remove the whole 'if' that does the "/watch" matching

     

    2) place the string "/with" and its redirect into data group

     

    3) test the whole thing by going to http://blabla/watch - works, go to http://blabla/watch/ - works, go to http://blabla/watch/bla - doesnt work. The last test was working in original setup, and is required to work in the data group scenario, but it seems that the starts_with clause in iRule does additional magic allowing to match with stuff after "/watch/", like "/watch/whatever/else"

     

     

    Any ideas why?
  • I'm out of ideas I'm afraid, sorry. Perhaps someone else who's able to test this can help out?
  • If you have "/watch" as a key in a data group named some_uri_redirects and do a lookup of "/watch", "/watch/", "/watch/something/else", or anything else that starts with "/watch" using [class match -value [HTTP::uri] starts_with some_uri_redirects], the command will return the key's value.

     

     

    If you're seeing something different, can you post a sanitized copy of the iRule and data group?

     

     

    Thanks, Aaron
  • Can anyone tell me what the behavior is when you try to do multiple redirects? It errors but what does it actually do?

     

     

    I am having an issue that I can hardly reproduce but I get complaints about. The issue is that when someone types in an address in Internet Explorer 8 or 9, the first result they get is a "Page Cannot be Displayed" (I cannot find any more detailed account of the error... ). If they hit refresh in the browser, the page loads. I can see in the ltm log that they are hitting the LTM and we are getting the multiple redirect not allow error. So I'm trying to figure out if these two are connected. In other browsers the error does not affect the page from loading.
  • I don't know the answer I'm afraid but I can help remove the error perhaps if you'd like to post the iRule?
  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    A Tcl error in an iRule (such as the multiple redirect error you're reporting) will typically reset the connection, so it definitely could be the cause of the "page cannot be displayed" errors.
  • Greetings all: I have been cleaning up my redirects to make sure I do not redirect if the connection had already been redirected. I do see the advice to combine iRules but I refuse to make a monolithic mess versus modular iRules (the programmer in me :) ).

     

    That being said, I have resorted to the following arrangement (and much of this comes from other tips I have read on this fantastic reference, DevCentral...)

     

    Any iRule that has a redirect, I do the following as the first line in the HTTP_REQUEST event:

     

    if {$gRespondOrRedirect}{ return };

     

    Then, any iRule that does a respond or redirect, I do the following (the 500 is just one example):

     

    set gRespondOrRedirect 1 HTTP::respond 500 noserver return

     

    This makes sure that future iRules can test $gRespondOrRedirect and return if necessary. The return after the respond is necessary or the same iRule will keep running.

     

    There may be other ways to do this, but that is what I came up with here. Note it occurs to be a New Feature Suggestion might be in order. With a couple small additions to the engine, the following might be possible:

     

    In any iRule that does a redirect:

     

    if {[HTTP::redirected]} { return };

     

    Then, in the actual respond or redirect, the following might help:

     

    HTTP::respond 500 noserver with_return

     

    with_return could be an option to the respond and redirect command to return from the current script at the time of the return.

     

    Of course, engineering gets to decide the validity of something like that to make sure it has general customer usefulness and does not break anything, but I thought I would see what the community thinks before I ask. Is there a better to accomplish this?

     

    Thanks,

     

    Tom Schaefer