Forum Discussion

ssl_b0y_87395's avatar
ssl_b0y_87395
Icon for Nimbostratus rankNimbostratus
Jul 18, 2011

Collapsing Lots of URIs into one with 2 Irules

Hi

 

 

Long time-lurker, first time poster! We've got a customer who'd been using F5 for some time for tactical LTM stuff, when "from high" a requirement came to collapse their six or seven web applications into a single, uniform URL and move the static web-content to the "parent" organisations website. Physically doing this was just impossible given the logistics of three distinct web farms physically in three different locations, for various reasons.

 

 

I knew enough about irules to know that the F5 could make this happen, but I didn't have time to fudge about trying to get it to work so we engaged F5 PS to put together a solution for us. Essentially some URLS are proxied, some directed to local pools and some are straight redirects. There is a mix of HTTP and HTTPS, some applications available in both, some only in HTTPS. After 2 days of hair pulling and teeth gnashing we have a solution, which thus far works. I've obfuscated the code as much as possible, but hopefully it still makes sense..Apologies for the lack of comments in the code; it's how F5 PS supplied it :) I've had to make a couple of tweaks as additional requirements have dropped out of the woodwork, but it's a pretty much as it came..

 

 

It's been 15 years since I've done any programming in anger, my knowledge of f5 and irules comes entirely from DevCentral..So I'm posting this for the benefit of others and would be interested in any feedback, good, bad, indifferent!

 

 

Attached to the HTTP VS:

 

 

when HTTP_REQUEST {

 

 

Pull out a specific URL and change the host headers to send to the default pool (server-side HH logic in this case)

 

string tolower [HTTP::host]

 

 

if { [HTTP::host] contains "bl.newurl.co.uk"} {HTTP::header replace Host bl.oldurl.co.uk}

 

 

 

Otherwise this is the main Primary URL

 

Anyone accessing the root will be directed back out to the parent site

 

Anyone Accessing any of the nominated "applications" will be redirected to the HTTPS VS and the PATH appended.

 

Everything else, send to the default Pool but change to host header so the site accepts it and presents the correct content.

 

else {

 

 

switch -glob [string tolower [HTTP::path]] {

 

"/" { HTTP::redirect http://www.parentorg.co.uk/division }

 

"/favicon.ico" { HTTP::respond 404 }

 

"/intenrnalapp1*" -

 

"/externalapp1*" -

 

"/externalapp2*" -

 

"/externalapp3*" { HTTP::redirect https://www.newurl.co.uk[HTTP::uri] }

 

default { HTTP::header replace Host www.oldurl.co.uk }

 

}

 

}

 

}

 

 

 

when HTTP_RESPONSE {

 

 

re-write the responses to take out the refereces to the various old URLs/file locations and insert the new ones.

 

 

STREAM::disable

 

if { [HTTP::is_redirect] } {

 

if { [HTTP::header Location] starts_with "http" } {

 

HTTP::header replace Location [string map "[URI::host [HTTP::header Location]] www.newurl.co.uk" [HTTP::header Location]]

 

}

 

} elseif { [HTTP::header Content-Type] starts_with "text" } {

 

STREAM::expression {@www.oldurl.co.uk@www.newurl.co.uk@@www.oldurl2.co.uk@www.newurl.co.uk@@bl.oldurl.co.uk@bl.newurl.co.uk@@}

 

STREAM::enable

 

}

 

}

2 Replies

  • And the one which is attached to the SSL VS:

     

     

    when HTTP_REQUEST {

     

     

    Do a force redirect anyone access the root

     

    Match the Paths to the various applications URLs

     

    Re-write the headers so back-end server still thinks it recieving "legacy" client requests

     

    Internalapp2 is not a public website and has an additional white list for live and test variations

     

    Final piece is to do with that there are two slight variations of the external app, essentially different branding paths to the same location

     

     

     

     

    switch -glob [string tolower [HTTP::path]] {

     

    "/" { HTTP::redirect http://www.parentcompany.co.uk/division }

     

    "/AP1*" {

     

    SSL::disable serverside

     

    pool pool_internalapp1

     

    HTTP::header replace Host ap1.oldurl.co.uk

     

    if { [string tolower [HTTP::path]] eq "/ap1" } {

     

    HTTP::path "/"

     

    } else {

     

    HTTP::path [string range [HTTP::path] 4 end]

     

    }

     

    }

     

    "/internalapp2_test*" {

     

    if { [class match [IP::client_addr] equals "Whitelisted_IPs"] } {

     

    SSL::disable serverside

     

    pool pool_Internalapp2_test

     

    HTTP::header replace Host internalapp2-test.oldurl.co.uk

     

    HTTP::path [string map { /internalapp2_test /app2_root } [HTTP::path]]

     

    } else {

     

    HTTP::redirect http://www.parentcompany.co.uk/division

     

    }

     

    }

     

    "/internalapp2*" {

     

    if { [class match [IP::client_addr] equals "Whitelisted_IPs"] } {

     

    SSL::disable serverside

     

    pool Pool_Internalapp2

     

    HTTP::header replace Host internalapp2.oldurl.co.uk

     

    HTTP::path [string map { /internalapp2 /app2_root } [HTTP::path]]

     

    } else {

     

    HTTP::redirect http://www.parentcompany.co.uk/division

     

    }

     

    }

     

    "/favicon.ico" { HTTP::respond 404 }

     

    "/*" {

     

    pool Pool_externalhost_SSL

     

    HTTP::header replace Host www.oldurl.co.uk

     

    if { [string tolower [HTTP::path]] starts_with "/externalapp2" } {

     

    HTTP::path [string map { /externalapp2 /externalapp2CS } [HTTP::path]]

     

    set map_externalapp2 1

     

    } else {

     

    set map_externalapp2 0

     

    }

     

    }

     

    }

     

    }

     

     

     

    when HTTP_RESPONSE {

     

     

    Re-write the HEADERS as they come back, directing HTTP to HTTPs and inserting the New URL to make sure the links work properly

     

     

     

     

    set header_var [HTTP::header "Referer"]

     

    STREAM::disable

     

    switch [LB::server pool] {

     

    "Pool_Internalapp2" {

     

    if { [HTTP::is_redirect] } {

     

    HTTP::header replace Location [string map {http https /app2_root /internalapp2 internalapp2.oldurl.co.uk www.newurl.co.uk} [HTTP::header Location]]

     

    log local0. "Found a redirect, directing to =$header_var"

     

    } elseif { [HTTP::header Content-Type] starts_with "text" } {

     

    STREAM::expression {@/app2_root@/internalapp2@}

     

    STREAM::enable

     

    }

     

    }

     

    "pool_Internalapp2_test" {

     

    if { [HTTP::is_redirect] } {

     

    HTTP::header replace Location [string map {http https /app2_root /internalapp2_test internalapp2-test.oldurl.co.uk www.newurl.co.uk} [HTTP::header Location]]

     

    } elseif { [HTTP::header Content-Type] starts_with "text" } {

     

    STREAM::expression {@/app2_root@/internalapp2_test@}

     

    STREAM::enable

     

    }

     

    }

     

    "Pool_externalhost_SSL" {

     

    if { [HTTP::is_redirect] } {

     

    if { [HTTP::header Location] starts_with "http" } {

     

    HTTP::header replace Location [string map "[URI::host [HTTP::header Location]] www.newurl.co.uk" [HTTP::header Location]]

     

    if { [URI::path [HTTP::header Location]] starts_with "/externalapp2" || [URI::path [HTTP::header Location]] starts_with "/externalapp2CS" } {

     

    if { [URI::protocol [HTTP::header Location]] eq "http" } {

     

    HTTP::header replace Location [string map {http https} [HTTP::header Location]]

     

    }

     

    }

     

    }

     

    } elseif { [HTTP::header Content-Type] starts_with "text" } {

     

    if { $map_externalapp2 } {

     

    STREAM::expression {@/externalapp2CS@/externalapp2@@www.oldurl.co.uk@www.newurl.co.uk@@www.oldurl2.co.uk@www.newurl.co.uk@}

     

    } else {

     

    STREAM::expression {@www.oldurl.co.uk@www.newurl.co.uk@@www.oldurl2.co.uk@www.newurl.co.uk@}

     

    }

     

    STREAM::enable

     

    }

     

    if { $map_externalapp2 } {

     

    if { [HTTP::is_redirect] } {

     

    HTTP::header replace Location [string map {/externalapp2CS /externalapp2} [HTTP::header Location]]

     

    }

     

    }

     

    unset map_externalapp2

     

    }

     

    pool_internalapp1 {

     

    if { [HTTP::is_redirect] } {

     

    if { [HTTP::header Location] starts_with "/" } {

     

    HTTP::header replace Location "/AP1[HTTP::header Location]"

     

    } elseif { [HTTP::header Location] starts_with "http" } {

     

    HTTP::header replace Location [string map "[URI::host [HTTP::header Location]] www.newurl.co.uk/AP1" [HTTP::header Location]]

     

    }

     

    } elseif { [HTTP::header Content-Type] starts_with "text" } {

     

    STREAM::expression {@src='/@src='/AP1/@@src="/@src="/AP1/@@action='/@action='/AP1@@action="/@action="/AP1@@href='/@href='/AP1@@href="/@href="/AP1@}

     

    STREAM::enable

     

    }

     

    }

     

    }

     

    }