Forum Discussion

mmcdougald's avatar
mmcdougald
Icon for Nimbostratus rankNimbostratus
Aug 17, 2023
Solved

iRule for multiple host to multiple pools and redirect path on one host.

I am not a coder so Im doing the best I can to develop an iRule.  I tried doing a mix of policies and leaving the irule for as it was but we ran into some conflicts. I am looking to see if anyone can "check my math" on the proposed rule.

What we are wanting this to do is.

We have a shared external IP that needs to direct based on host name to a pool. on the second host we also need to change some paths. 

Aside from adding the new host to the iRule it is working currently.  We are adding in the first section "Host1" The current iRule only works on Host2 and below. 

when HTTP_REQUEST {
switch [string tolower [HTTP::host]] {
"HOST1" {
pool HOST1
log local0. "Matched HOST1"
}
"HOST2" {
set received_path [string tolower [HTTP::path]]
log local0. "Matched HOST2"
switch -glob -- [string tolower [HTTP::path]] {
"/v1*" {
pool 9443-POOL
return
}
"/oauth*" {
pool 9443-POOL
return
}
"/PATH1*" {
set uri [string map -nocase {"/PATH1" "/PATH2"} [HTTP::uri]]
log local0. "$uri was modified.."
HTTP::uri $uri
pool inbound-Pool
return
}
default {
log local0. "$received_host could not find path $received_path"
HTTP::respond 404 content { <html><head><title>Page Not Found</title></head><body>HOST2 has failed to find a received_path match.</body></html> } Received-Path $rec
}
}
}
default {
log local0. "Could not find received host $received_host"
HTTP::respond 404 content { <html><head><title>Page Not Found</title></head><body>The iRule has failed to find a received_host match.</body></html> } Received-Host $received_host
}
}
}

  • mmcdougald The following has some updates to your iRule such as spacing and best practices. In addition I would like to note that you are attempting to use variable "received_host" but you actually have created that variable or set any value to it.

    when HTTP_REQUEST priority 500 {
    
        switch -- [HTTP::host] {
            "HOST1" {
                pool HOST1
                log local0. "Matched HOST1"
            }
            "HOST2" {
                set RECEIVED_PATH [string tolower [HTTP::path]]
                log local0. "Matched HOST2"
    
                switch -- [string tolower [HTTP::path]] {
                    "/v1*" {
                        pool 9443-POOL
                        return
                    }
                    "/oauth*" {
                        pool 9443-POOL
                        return
                    }
                    "/PATH1*" {
                        set URI [string map -nocase {"/PATH1" "/PATH2"} [HTTP::uri]]
                        log local0. "${URI} was modified.."
                        HTTP::uri ${URI}
                        pool inbound-Pool
                        return
                    }
                    default {
                        log local0. "$received_host could not find path ${RECEIVED_PATH}"
                        HTTP::respond 404 content { <html><head><title>Page Not Found</title></head><body>HOST2 has failed to find a {RECEIVED_PATH} match.</body></html> } Received-Path $rec
                    }
                }
    
            }
            default {
                log local0. "Could not find received host $received_host"
                HTTP::respond 404 content { <html><head><title>Page Not Found</title></head><body>The iRule has failed to find a received_host match.</body></html> } Received-Host $received_host
            }
        }
    
    }

    Now it is possible that because you are testing this for Host2 and then testing Host1 which causes it not to work appropriately. You might try creating a /32 OneConnect profile and applying it to the Virtual Server (VS) in question to see if that resolves your issue. If this change to the VS does resolve your issues it's because by default the F5 does not parse every single HTTP request over a TCP connection but only the first request and makes any following decisions on that TCP connection based on where the initial request was sent. Other than what I have mentioned this iRule should function for Host1 and you will no longer have an error generated once you define the define variable "received_host" in your iRule.

2 Replies

  • mmcdougald The following has some updates to your iRule such as spacing and best practices. In addition I would like to note that you are attempting to use variable "received_host" but you actually have created that variable or set any value to it.

    when HTTP_REQUEST priority 500 {
    
        switch -- [HTTP::host] {
            "HOST1" {
                pool HOST1
                log local0. "Matched HOST1"
            }
            "HOST2" {
                set RECEIVED_PATH [string tolower [HTTP::path]]
                log local0. "Matched HOST2"
    
                switch -- [string tolower [HTTP::path]] {
                    "/v1*" {
                        pool 9443-POOL
                        return
                    }
                    "/oauth*" {
                        pool 9443-POOL
                        return
                    }
                    "/PATH1*" {
                        set URI [string map -nocase {"/PATH1" "/PATH2"} [HTTP::uri]]
                        log local0. "${URI} was modified.."
                        HTTP::uri ${URI}
                        pool inbound-Pool
                        return
                    }
                    default {
                        log local0. "$received_host could not find path ${RECEIVED_PATH}"
                        HTTP::respond 404 content { <html><head><title>Page Not Found</title></head><body>HOST2 has failed to find a {RECEIVED_PATH} match.</body></html> } Received-Path $rec
                    }
                }
    
            }
            default {
                log local0. "Could not find received host $received_host"
                HTTP::respond 404 content { <html><head><title>Page Not Found</title></head><body>The iRule has failed to find a received_host match.</body></html> } Received-Host $received_host
            }
        }
    
    }

    Now it is possible that because you are testing this for Host2 and then testing Host1 which causes it not to work appropriately. You might try creating a /32 OneConnect profile and applying it to the Virtual Server (VS) in question to see if that resolves your issue. If this change to the VS does resolve your issues it's because by default the F5 does not parse every single HTTP request over a TCP connection but only the first request and makes any following decisions on that TCP connection based on where the initial request was sent. Other than what I have mentioned this iRule should function for Host1 and you will no longer have an error generated once you define the define variable "received_host" in your iRule.

    • mmcdougald's avatar
      mmcdougald
      Icon for Nimbostratus rankNimbostratus

      Thank you,

      So removing the Var and just using the [HTTP::host]  instead would work also? The logging of the event is less of a concern as long as the irule gets the traffic to the correct location. 

      I think the copy and paste might be messing with the formatting. 

       

      when HTTP_REQUEST priority 500 {

       

          switch -- [HTTP::host] {

              "HOST1" {

                  pool HOST1

                  log local0. "Matched HOST1"

              }

              "HOST2" {

                  set RECEIVED_PATH [string tolower [HTTP::path]]

                  log local0. "Matched HOST2"

       

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

                      "/v1*" {

                          pool 9443-POOL

                          return

                      }

                      "/oauth*" {

                          pool 9443-POOL

                          return

                      }

                      "/PATH1*" {

                          set URI [string map -nocase {"/PATH1" "/PATH2"} [HTTP::uri]]

                          log local0. "${URI} was modified.."

                          HTTP::uri ${URI}

                          pool inbound-Pool

                          return

                      }

                      default {

                          log local0. "[HTTP::host] could not find path ${RECEIVED_PATH}"

                          HTTP::respond 404 content { <html><head><title>Page Not Found</title></head><body>HOST2 has failed to find a {RECEIVED_PATH} match.</body></html> } Received-Path $rec

                      }

                  }

       

              }

              default {

                  log local0. "Could not find received host [HTTP::host]"

                  HTTP::respond 404 content { <html><head><title>Page Not Found</title></head><body>The iRule has failed to find a Host matching in the iRule.</body></html> } Received-Host [HTTP::host]

              }

          }

       

      }