Forum Discussion

nich_66940's avatar
nich_66940
Icon for Nimbostratus rankNimbostratus
Sep 27, 2007

Rewriting 302 redirects

We have come 'intelligent' website code that redirects the user to SSL pages based on what the developer originally thought best.

 

 

As we are using SSL offloading on the BigIP this has meant that we need to set the redirect to http to stop the site from performing infinite loops as the site detects that the BigIP has sent the request to port 80, despite the fact that the contention is acceptably secured.

 

 

So what I want to do is intercept 302 redirects from the site that match certain URLs and rewrite them to https.

 

 

Ie if a redirect from the site tells the user to connect to http://example.com/secure/* I want to redirect it to https://example.com/secure/*

 

 

Using the profile option in LTM profiles creates other problems with pages that really should be redirected to port 80.

 

 

Going through previously published results I assume I want to do some magic like:

 

when HTTP_RESPONSE {

 

if { [HTTP::status] == "302" } {

 

if { [HTTP::header exists "Location"] } {

 

if { string compare -nocase -length 26 [HTTP::header "Location"] "http://example.com/secure/" == 0} {

 

HTTP::header replace "Location" [echo [HTTP::header "Location"] | regexp s/http/https ]

 

}

 

}

 

}

 

}

 

 

Any help is greatly appreciated.

 

 

nich.

 

 

update: more guesses on my behalf for code needed

5 Replies

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    Nice work! This looks really close, not to mention tricky! You can simplify it a little though.

    
    when HTTP_RESPONSE {
      if { [HTTP::status] == "302" } {
        if { [HTTP::header "Location"] starts_with "http://example.com/secure/" } {
            HTTP::header replace "Location" [string map {http https} [HTTP::header "Location"] ]
        }
      }
    }

    Of course, it sounds like you're going to have multiple URLs you want to check for in the location header. In this case you'll want to make use of either switch or matchclass, depending on how many you want to check.

    That would look something like"

    
    when HTTP_RESPONSE {
      if { [HTTP::status] == "302" } {
        switch -glob [string tolower [HTTP::header "Location"] ] {
          "http://example.com/secure/*" -
          "http://example.com/private/*" -
          "http://example.com/restricted/*" -
          "http://someothersite.com/keepout/*" -
          "http://reallyprivatestuff.com/shouldbeencrypted/*" -
          default {
            HTTP::header replace "Location" [string map {http https} [HTTP::header "Location"] ]
          }
        }
      }
    }

    HTH,

    Colin
  • Thanks that was really helpful. I think I am going to use matchclass due to the number of URLs to rewrite.

     

     

    Current code is below and this appears to be doing the right thing.

     

     

    
    when HTTP_RESPONSE {
      if { [HTTP::status] == "302" } {
         if { [matchclass [string tolower [HTTP::header "Location"]] starts_with $::sslLocations] } {
            HTTP::header replace "Location" [string map {http https} [HTTP::header "Location"] ]
         }
      }
    }

     

     

    nich.
  • I've been using a variant of this rule and the upgrade to version 11 has broken it. The variable can no longer be read. Any suggestions?
  • mvcheney,

     

     

    You should remove the $:: prefix from the sslLocations data group reference in the iRule for version 9.4.4 or higher.

     

     

    Aaron