Forum Discussion

Tony_Hobson_189's avatar
Tony_Hobson_189
Icon for Nimbostratus rankNimbostratus
May 06, 2015

Cannot rewrite response.redirect using iRules

Hello all

Overview:

In a hosted environment, the edge is controlled by the Hosting company F5. This F5 terminates HTTPS and forwards HTTP to our virtual F5. This is running 11.6. Only HTTPS is allowing on the edge.

For the incoming request, we rewrite the hostname as the downstream server requires a specific host name binding to work.

For the response, we re-write any HTML links to match the external URL and also enforce https:// on the front of the URL.

This is working, except for response.redirect. For some reason these are not getting re-written and we cannot pinpoint why these are being missed. We have try using STREAM and HTTP::payload re-writing, but in each case the response.redirect is not rewritten. As such we can see the client attempts to connect to HTTP and this is blocked.

Here are the 2 iRules we have tried:

iRULE using STREAM

when HTTP_REQUEST {

   Rewrite host
  HTTP::header replace Host test.apply.site.com

   Disable the stream filter for all requests
  STREAM::disable

   Prevent server from sending compressed response
  HTTP::header remove "Accept-Encoding"

   Don't allow data to be chunked
  if { [HTTP::version] eq "1.1" } {

   Force downgrade to HTTP 1.0 but still allow keep-alive

   Check if this is a keep alive connection
  if { [HTTP::header is_keepalive] } {

      Replace the connection header value with "Keep-Alive"
    HTTP::header replace "Connection" "Keep-Alive"

  }

   Set server side request to version 1.0 to force server to respond without chunking
  HTTP::version "1.0"

  }

}
when HTTP_RESPONSE {

  log local0. "HTTP_RESPONSE_BEFORE: [HTTP::payload]"

  Check response type is text
  if {[HTTP::header value Content-Type] contains "text"}{

     Replace http:// with https://
    STREAM::expression {@http://@https://@}

     Enable the stream filter for this response only
    STREAM::enable

    log local0. "HTTP_RESPONSE_AFTER: [HTTP::payload]"

  }
}

when STREAM_MATCHED {
  log local0. "STREAM_MATCHED: [STREAM::match]"
}

iRULE using HTTP::payload rewrite:

when HTTP_REQUEST {

   Rewrite host
  HTTP::header replace Host test.apply.site.com

   Prevent server from sending compressed response
  HTTP::header remove "Accept-Encoding"

   Don't allow data to be chunked
  if { [HTTP::version] eq "1.1" } {

   Force downgrade to HTTP 1.0 but still allow keep-alive

   Check if this is a keep alive connection
  if { [HTTP::header is_keepalive] } {

      Replace the connection header value with "Keep-Alive"
    HTTP::header replace "Connection" "Keep-Alive"

  }

   Set server side request to version 1.0 to force server to respond without chunking
  HTTP::version "1.0"

  }
}

when HTTP_RESPONSE {

   Check response type is text
  if {[HTTP::header value Content-Type] contains "text"}{

     Determine how much content to collect (no more than 1MB)
    if {[HTTP::header exists "Content-Length"] && [HTTP::header "Content-Length"] <= 1048576}{

      set content_length [HTTP::header "Content-Length"]

    } else {

       Only collect first 1MB for response (SOL6578)
      set content_length 1048576
    }

    if { $content_length > 0 }{

       Trigger collection of payload
      HTTP::collect $content_length

      log local0. "[IP::client_addr]:[TCP::client_port]: Collecting content: $content_length"
    }
  }
}

when HTTP_RESPONSE_DATA {

  log local0. "[IP::client_addr]:[TCP::client_port]: ORI Payload: [HTTP::payload]"

   Replace http: https:
  set newdata [string map {/http:/ /https:/} [HTTP::payload]]

  log local0. "[IP::client_addr]:[TCP::client_port]: MOD Payload: [HTTP::payload]"

   HTTP::payload replace 0 $content_length $newdata
  HTTP::payload replace 0 $content_length $newdata

}

What are we missing..? Any help would be great.

Thanks in advance

  • We have try using STREAM and HTTP::payload re-writing, but in each case the response.redirect is not rewritten.

     

    where is it? is it http response header?

     

    HTTP::collect and stream (with http profile) works on http payload (not http header). you may use HTTP::is_redirect to check redirection and modify location header using HTTP::header.

     

    HTTP::is_redirect

     

    https://devcentral.f5.com/wiki/iRules.HTTP__is_redirect.ashx

     

  • Hello

    Your suggestion was spot-on. Many thanks.

    If anyone needs an example, here is what we used:

    when HTTP_RESPONSE {
       Set DEBUG
      set DEBUG 0
    
      if { [HTTP::is_redirect] }{
    
        if { $DEBUG } { log local0. "*** REQUEST REDIRECT BEFORE *** STATUS:[HTTP::status] LOCATION:[HTTP::header Location]" }
    
        HTTP::header replace Location [string map -nocase { "http://" "https://" } [ HTTP::header Location] ]
    
        if { $DEBUG } { log local0. "*** REQUEST REDIRECT AFTER *** STATUS:[HTTP::status] LOCATION:[HTTP::header Location]" }
    
      }
    
      Check response type is text
      if {[HTTP::header value Content-Type] contains "text"}{
    
        STREAM::expression {@http://@https://@}
    
         Enable the stream filter for this response only
        STREAM::enable
      }
    }