Forum Discussion

Devonion_22138's avatar
Devonion_22138
Icon for Nimbostratus rankNimbostratus
May 14, 2012

Redirect to test server and rewrite returned links

I'm trying to write an irule so that I can use a cloned live webserver to test a PHP upgrade.

irule basically changes host header from www.dev.ourserver.com to www.ourserver.com and this part works fine if I only include the HTTP_REQUEST section.

However, when I try to add the HTTP_RESPONSE and HTTP_RESPONSE_DATA sections, I start getting "server hangup"s.

Any help would be most appreciated.

My irule is as follows


when HTTP_REQUEST {
    set DEBUG 1
    if { [HTTP::version] equals "1.1" } {
        if { [HTTP::header is_keepalive] } {
            HTTP::header replace "Connection" "Keep-Alive"
            HTTP::header remove Accept-Encoding
        }
        HTTP::version "1.0"
        set collected 0
    }
    if { [HTTP::host] equals "devserverurl"} {
        HTTP::header replace "Host" "serverurl"
        if { $DEBUG } { log local0. "irule used by IP: [IP::client_addr] - requesting [HTTP::host][HTTP::uri]" }
    }
}
when HTTP_RESPONSE {
     Get the content length so we can request the data to be
     processed in the HTTP_RESPONSE_DATA event.
    set DEBUG 1
    if { [HTTP::header exists "Content-Length"] } {
        set content_length [HTTP::header "Content-Length"]
    } else {
        set content_length 0
    }
     content_length of 0 indicates chunked data (of unknown size)
    if { $content_length > 0 && $content_length < 1024001 } {
         set collect_length $content_length
     } else {
         set collect_length 1024000
     }
     if { $DEBUG } {
         log local0. "[IP::client_addr]:[TCP::client_port]: Content Length:: $content_length    Collect Length: $collect_length"
     }
    if { $collect_length > 0 } {
        HTTP::collect $collect_length
    }
}
when HTTP_RESPONSE_DATA {
    set DEBUG 1
   regsub -all "serverurl" [HTTP::payload] "devserverurl" newdata
    if { $DEBUG } {
         log local0. "PAYLOAD before replace: [HTTP::payload]"
    }
    HTTP::payload replace 0 $content_length $newdata
    if { $DEBUG } {
         log local0. "PAYLOAD after replace: [HTTP::payload]"
     }
     HTTP::release
      if { $content_length > 0 } {
         for unchunked data, calculate the remaing length & re-collect if necessary
         the HTTP_RESPONSE_DATA event will be triggered again when each collection is complete
         set collect [expr {$collected + $collect_length}]
         set remaining [expr {$content_length - $collected}]
         if { $remaining > 0 } {
             if { $remaining < $collect_length } {
                 set collect_length $remaining
             }
             HTTP::collect $collect_length
         }
     } else {
     chunked responses data, continue collecting in 1MB chunks.  Watch for hanging responses here.
     The HTTP_RESPONSE_DATA event will be triggered again when each ccollection is complete
         HTTP::collect $collect_length
     }
}

Many Thanks
  • Sorry,

     

     

    I'd just like to add that if I create a very simple staic html page with just a link in there to make sure it gets rewritten this works, so it seems the issues is with more complex pages.
  • Hi Devonion,

     

     

    Have you considered using a Stream Profile?

     

     

    This can be done with the default LTM Stream Profile or via an iRule that uses the STREAM::expression, STREAM::enable, and STREAM::disable commands.

     

     

    This is the methodology that is used where I work to allow the same production code to be promoted through the test environments without being changed, but allows the different environment URL's to be modified on the fly.

     

     

    Hope this idea helps.
  • Hi Michael,

     

    My first attempt actually used the STREAM::expression - but I seemed to get inconsistent results - it seemed to work one minute, then pressing CTRL-F5 to reload page in a brower and it didn't rewrite the links. Basically I did the same as the irule above in the HTTP_REQUEST, but added a STREAM::disable at the start. Then did a STREAM::match and finally the STREAM::expression and STREAM::enable (I think)

     

    If I still have a copy of the irule I will post tomorrow.

     

    However, I guess I should try the default STREAM profile as that seems the simplest way to go, but I inherited this F5 and I'm not 100% sure what was there by default and what custom additions I've inherited - and this is all new to me and of course this needed sorting yesterday! So I've not got as much knowledge as I'd like before I've had to just dive in.

     

    I appreciate the reply, thanks!
  • OK, so I went back to the drawing board, read some more and realised I was completely over complicating things here.

     

    I kept my http_request section to rewrite the header, works as expected.

     

    I then did as you suggested and used the default STREAM profile and this now works a treat.

     

    So!! Last piece of the puzzle is a valid replace command in the target of my stream profile.

     

    I've left the source empty and in the target I've added @www.ourserver.com@www.dev.ourserver.com@

     

    Now this is great for testing, but we have loads of Virtual Hosts, some with different domains and so I need a regex

     

    I tried the following but could not save the profile due to an error about it being bad

     

    It works in sed, but I know only basic regex is supported in the stream profile, but I thought this was pretty basic.

     

    This is a simplified version but syntax is same as my target.

     

    @www\(.*\).com@www.dev\1.com@

     

    Is this sort of substitution possible in the stream profile? I get "bad regular expression in stream" error when I try to save this.

     

    Thanks

     

  • Hi Michael,

     

    That link is where I got the information I needed to get this working - unfortunately, it seems like backreferences are not supported in the stream profile :(