Forum Discussion

Shadow's avatar
Shadow
Icon for Cirrus rankCirrus
May 06, 2024

iRule resulting in too many redirects

 

I have two requirements with my virtual server.
 
1. A redirect to /pc/service/SSOLogin
2. 24 hour persistence based on the JSESSIONID cookie in the request header.
 
The first one was accomplished early on with a policy that redirects to location '/pc/service/SSOLogin' at request time. This has worked without any issues until I tried to implement the JSESSIONID persistence. 
 
To accomplish the second, I created an iRule to be used with the Universal persistence profile. When I implemented this persistence profile, the redirect policy no longer worked. My assumption was that the iRule and the policy were conflicting with each other. To resolve this, I created a single iRule to handle both of these requirements.
 
Now, I am getting too many redirects. The iRule is below.
 
 
 
when HTTP_RESPONSE {
## PERSISTENCE
# If the JSESSIONID exists, we'll pass the cookie along
    if { [HTTP::cookie exists "JSESSIONID"] } {
        persist add uie [HTTP::cookie "JSESSIONID"] 86400
    }
}
 
when HTTP_REQUEST {
## PERSISTENCE
# If the JSESSIONID exists, we'll maintain that persistence
    if { [HTTP::cookie exists "JSESSIONID"] } {
        persist uie [HTTP::cookie "JSESSIONID"]
    }
 
## REDIRECT
    # This grabs the base url from the incoming request
# For Example, https://my.site.com/some/path the base_url is set to https://my.site.com
set base_url "https://[HTTP::host]"
 
    # Defining the new path
    set new_path "/pc/service/SSOLogin"
 
    # Construct the new URL
# For example, https://my.site.com/pc/service/SSOLogin
    set new_url "$base_url$new_path"
 
    # Redirect to the new URL
    HTTP::redirect $new_url
 
}
  • The way it's written, it seems like it will always send a redirect response. I assume you probably would like it to NOT redirect sometimes.

    In what way do you want the BIG-IP tell the difference between when you want it to redirect and when you don't?

    • Shadow's avatar
      Shadow
      Icon for Cirrus rankCirrus

      The original policy was designed for it to always redirect to the SSO path. It should always strip whatever path is there and append the SSO path. I can't imagine that would cause the too many redirects. I'm assuming there is something wrong that is causing an https/http loop, but I am not proficient enough in writing tcl to know if there is an error in the code.

  • Lucas_Thompson did get me thinking about the flow. I moved the "HTTP::redirect $new_url" to HTTP_RESPONSE thinking that it might be because it is redirecting to itself and each request was doing the same thing over and over. It didn't work, but the logic to me seems sound. 

    Should the HTTP::redirect be in the response?

    Am I just mucking up the logic here? Should I check to make sure the incoming path is correct and if not, then redirect?

  • I rewrote the iRule to add the logic that Lucas_Thompson referenced to determine when I need to redirect. I can't find anything wrong with the code. However, I get ERR_CONNECTION_RESET.

    For added information, I am using this iRule in conjunction with Universal persistence.

    The new code is below.

     

    when HTTP_RESPONSE {

    ## PERSISTENCE

        # If the JSESSIONID exists, we'll pass the cookie along

        if { [HTTP::cookie exists "JSESSIONID"] } {

            persist add uie [HTTP::cookie "JSESSIONID"] 86400

        }

     

    ## REDIRECT

        # Check if the request path is not "/pc/service/SSOLogin"

        if { $url_redirect } {

            # Redirect to the new URL

            HTTP::redirect $new_url

        }

    }

     

    when HTTP_REQUEST {

    ## PERSISTENCE

        # If the JSESSIONID exists, we'll maintain that persistence

        if { [HTTP::cookie exists "JSESSIONID"] } {

            persist uie [HTTP::cookie "JSESSIONID"]

        }

     

    ## REDIRECT

         # Check if the request path is already "/pc/service/SSOLogin"

         # If so, set the url_redirect to false. If not, set it to true.

         if { [string equal [HTTP::uri] "/pc/service/SSOLogin"] } {

              set $url_redirect 0; 

         } else {

              set $url_redirect 1; 

              # This grabs the base URL from the incoming request

              # For example, https://my.site.com/some/path the base_url is set to https://my.site.com

              set base_url "https://[HTTP::host]"

     

              # Defining the new path

              set new_path "/pc/service/SSOLogin"

     

               # Construct the new URL

               # For example, https://my.site.com/pc/service/SSOLogin

               set new_url "$base_url$new_path"

         }

    }

     

    • Lucas_Thompson's avatar
      Lucas_Thompson
      Icon for Employee rankEmployee

      Super! It sounds like you're able to test these changes rapidly and have a good test environment.

      A few pointers while you're developing code:

      1- Keep a ssh session open and watch the log file output from ```tail -f /var/log/ltm``` while you're working on it. RSTs and other misbehavior will be easy to spot. Any syntax error or unreferenced variable will cause BIG-IP to RST the connection and produce a log message.

      2- Because iRules don't really have a debugger, you have to use the "debug by printf" method. This means peppering your code with log statements during development. Like, before EACH command you run something like this:

      log local0. "about to set persist entry on [HTTP::cookie JSESSIONID]"
      persist uie [HTTP::cookie "JSESSIONID"]
      or
      log local0. "about to send 302 redirect to $new_url" 
      HTTP::redirect 

      3- If you're "done" inside an event and want to finish up, you can use the ```return``` command to exit the event. It seems like in your code that you want to ```persist``` OR ```rerdirect```, but not both.

      4- The ```set``` command sets variables. Once set, variables are generally available later on in the same flow, but you should always check them first to make sure the data you expect is there. You can use the ```info exists``` command to achieve this. See this discussion for more in-depth about that: BIG-IP : iRule test that variable exists and has certain value | DevCentral

       

       

       

  • I think my real problem is that I need to set a 301 permanent redirect.