Forum Discussion

minnoce944's avatar
minnoce944
Icon for Nimbostratus rankNimbostratus
Jul 30, 2014

http rewrite and pool selection based on method

We have a requirement to perform URI rewrites for specific paths and direct that request to the appropriate pool. As an added bonus we also need to inspect the http method used to make sure we are sending to the appropriate pool.

I've came up with the following rule so far but getting a compile error error: /Common/irulename:10: error: [command is not valid in the current scope][if { [string tolower [HTTP::method]] eq "get" } {

Please help and also let me know if there is a better way to write this as i'm still learning irules.

first uri check to determine if it matches
method can be get or put, rewrite URI and route to appropriate pool
when HTTP_REQUEST {
  if {( [string tolower [HTTP::uri]] eq "/IMSWeb/IMSServlet" ) } {
        HTTP::uri "/ReservationService/IMSServlet"
      pool pool1.tcp.8780
     }
       }
   check to determine appropriate method, perform switch statement
    if { [string tolower [HTTP::method]] eq "get" } {
       method is get, need to rewrite URI and route to appropriate pool
       switch -glob [string tolower [HTTP::uri] ] {
            "/IMSWeb/rest/services/inventory" {
         HTTP::uri "/ReservationService/IMSServlet"
          pool pool1.tcp.8780
         }
           "/IMSWeb/Lookup" {
          HTTP::uri "/ReservationService/UI/invLookUp"
            pool pool1.tcp.8780
         }
       }
   }
   else { [string tolower [HTTP::method]] eq "put" } {
     method is put, need to rewrite host & URI and route to appropriate pool
        switch -glob [string tolower [HTTP::uri] ] {
            "/IMSWeb/rest/services/item" {
          HTTP::host "foo.com"
          HTTP::uri "/iasserver/rest/services/item"
           pool pool2.tcp.80
           }
           "/IMSWeb/rest/services/inventory" {
         HTTP::host "foo.com"
          HTTP::uri "/iasserver/rest/services/inventory"
          pool pool2.tcp.80
           }       
        }
   }
}

6 Replies

  • Arie's avatar
    Arie
    Icon for Altostratus rankAltostratus

    You have a wayward closing brace on line 6, which closes the event "HTTP_REQUEST". HTTP::method is therefore executed outside of that scope.

     

  • Arie's avatar
    Arie
    Icon for Altostratus rankAltostratus

    I can't test it right now, but try this:

    when HTTP_REQUEST {
      if {( [string tolower [HTTP::uri]] eq "/IMSWeb/IMSServlet" ) } {
            HTTP::uri "/ReservationService/IMSServlet"
          pool pool1.tcp.8780
         }
    
       check to determine appropriate method, perform switch statement
        if { [string tolower [HTTP::method]] eq "get" } {
           method is get, need to rewrite URI and route to appropriate pool
           switch -glob [string tolower [HTTP::uri] ] {
                "/IMSWeb/rest/services/inventory" {
             HTTP::uri "/ReservationService/IMSServlet"
              pool pool1.tcp.8780
             }
               "/IMSWeb/Lookup" {
              HTTP::uri "/ReservationService/UI/invLookUp"
                pool pool1.tcp.8780
             }
           }
       }
       else { [string tolower [HTTP::method]] eq "put" } {
         method is put, need to rewrite host & URI and route to appropriate pool
            switch -glob [string tolower [HTTP::uri] ] {
                "/IMSWeb/rest/services/item" {
              HTTP::host "foo.com"
              HTTP::uri "/iasserver/rest/services/item"
               pool pool2.tcp.80
               }
               "/IMSWeb/rest/services/inventory" {
             HTTP::host "foo.com"
              HTTP::uri "/iasserver/rest/services/inventory"
              pool pool2.tcp.80
               }       
            }
       }
    }
    
  • thanks for the response, but still getting compile errors:

    01070151:3: Rule [/Common/meh] error: /Common/meh:9: error: [undefined procedure:

    method is put, need to rewrite host & URI and route to appropriate pool

    Here is what I'm using:

    first uri check to determine if it matches
    method can be get or put, rewrite URI and route to appropriate pool
    when HTTP_REQUEST {
      if {( [string tolower [HTTP::uri]] eq "/IMSWeb/IMSServlet" ) } {
            HTTP::uri "/ReservationService/IMSServlet"
          pool pool1.tcp.8780
         }
       check to determine appropriate method, perform switch statement
        if { [string tolower [HTTP::method]] eq "get" } {
           method is get, need to rewrite URI and route to appropriate pool
           switch -glob [string tolower [HTTP::uri] ] {
                "/IMSWeb/rest/services/inventory" {
             HTTP::uri "/ReservationService/IMSServlet"
              pool pool1.tcp.8780
             }
               "/IMSWeb/Lookup" {
              HTTP::uri "/ReservationService/UI/invLookUp"
                pool pool1.tcp.8780
             }
           }
       }
       else { [string tolower [HTTP::method]] eq "put" } {
         method is put, need to rewrite host & URI and route to appropriate pool
            switch -glob [string tolower [HTTP::uri] ] {
                "/IMSWeb/rest/services/item" {
              HTTP::host "foo.com"
              HTTP::uri "/iasserver/rest/services/item"
               pool pool2.tcp.80
               }
               "/IMSWeb/rest/services/inventory" {
             HTTP::host "foo.com"
              HTTP::uri "/iasserver/rest/services/inventory"
              pool pool2.tcp.80
               }       
            }
       }
    }
    
  • I changed else to elseif and http::host to http::header replace Host since i'm on ver 11.4. It compiles fine now. I'll post back after my testing results.

    Below is updated version:

    first uri check to determine if it matches
    method can be get or put, rewrite URI and route to appropriate pool
    when HTTP_REQUEST {
      if {( [string tolower [HTTP::uri]] eq "/IMSWeb/IMSServlet" ) } {
            HTTP::uri "/ReservationService/IMSServlet"
          pool pool1.tcp.8780
         }
       check to determine appropriate method, perform switch statement
        if { [string tolower [HTTP::method]] eq "get" } {
           method is get, need to rewrite URI and route to appropriate pool
           switch -glob [string tolower [HTTP::uri] ] {
                "/IMSWeb/rest/services/inventory" {
             HTTP::uri "/ReservationService/IMSServlet"
             pool pool1.tcp.8780
             }
               "/IMSWeb/Lookup" {
              HTTP::uri "/ReservationService/UI/invLookUp"
                pool pool1.tcp.8780
             }
           }
       }
       elseif { [string tolower [HTTP::method]] eq "put" } {
         method is put, need to rewrite host & URI and route to appropriate pool
            switch -glob [string tolower [HTTP::uri] ] {
              "/IMSWeb/rest/services/item" {
              HTTP::header replace Host "pool2"
              HTTP::uri "/iasserver/rest/services/item"
              pool pool2.tcp.80
               }
              "/IMSWeb/rest/services/inventory" {
              HTTP::header replace Host "pool2"
              HTTP::uri "/iasserver/rest/services/inventory"
              pool pool2.tcp.80
               }       
            }
       }
    }
    
  • ok back again..after fixing a few case sensitivity issues with my original code, this is working for the most part. I'm currently having issues with replacing the http host with a new value. I'm currently using 'http::header replace Host' but the new value doesn't appear to be used from my debug output.

     

    Here is the curl command i'm using with the original request. curl -X put meh http://pool1:8380/IMSWeb/rest/services/inventory

     

    Here is the irule debug output: Jul 31 17:13:20 lb-core-01 info tmm1[10029]: Rule /Common/pool1.tcp.8380.irule : original request:pool1:8380:/IMSWeb/rest/services/inventory Jul 31 17:13:20 lb-core-01 info tmm1[10029]: Rule /Common/pool1.tcp.8380.irule : using put method Jul 31 17:13:20 lb-core-01 info tmm1[10029]: Rule /Common/pool1.tcp.8380.irule : processing method put for /imsweb/rest/services/inventory Jul 31 17:13:20 lb-core-01 info tmm1[10029]: Rule /Common/pool1.tcp.8380.irule : The new host and uri is: pool1:8380:/iasserver/rest/services/inventory

     

    As you can see the URI value is updated correctly from /IMSWeb/rest/services/inventory to /iasserver/rest/services/inventory but the host value is still the original value.

     

    How can i fix this? Also, it looks like i'll also need to modify the port as well since i'm sending this traffic to port 80 vs 8380. I would imagine once i get the correct procedure to rewrite the host i could just add :80 to the end of that.

     

    Thanks,

     

    --Mike

     

    Here is my updated irule:

     

    pool1.tcp.8380.irule v1.0
    7-31-2014 xxx
    
    first uri check to determine if it matches
    method can be get or put, rewrite URI and route to appropriate pool
    when HTTP_REQUEST {
    log local0. "original request:[HTTP::host]:[HTTP::uri]"
      if {( [string tolower [HTTP::uri]] eq "/imsweb/imsservlet" ) } {
          log local0. "condition met - routed to pool1.tcp.8780"     
          HTTP::uri "/reservationservice/imsservlet"
          pool pool1.tcp.8780
         }
       check to determine appropriate method, perform switch statement
        if { [string tolower [HTTP::method]] eq "get" } {
           method is get, need to rewrite URI and route to appropriate pool
           log local0. "using get method"
           switch -glob [string tolower [HTTP::uri] ] {
                "/imsweb/rest/services/inventory" {
             log local0. "processing method get for /imsweb/rest/services/inventory"
             HTTP::uri "/reservationservice/imsservlet"
             pool pool1.tcp.8780
             }
               "/imsweb/lookup" {
              log local0. "processing method get for /imsweb/lookup"
              HTTP::uri "/reservationservice/ui/invlookup"
                pool pool1.tcp.8780
             }
           }
       }
       elseif { [string tolower [HTTP::method]] eq "put" } {
         method is put, need to rewrite host & URI and route to appropriate pool
            log local0. "using put method"
            switch -glob [string tolower [HTTP::uri] ] {
              "/imsweb/rest/services/item" {
              log local0. "processing method put for /imsweb/rest/services/item"
              HTTP::header replace Host "pool2"
              HTTP::uri "/iasserver/rest/services/item"
              pool pool2.tcp.80
               }
              "/imsweb/rest/services/inventory" {
              log local0. "processing method put for /imsweb/rest/services/inventory"
              HTTP::header replace Host "pool2"
              HTTP::uri "/iasserver/rest/services/inventory"
              log local0. "The new host and uri is: [HTTP::host]:[HTTP::uri]"
              pool pool2.tcp.80
              }       
            }
       }
    }
    • minnoce944's avatar
      minnoce944
      Icon for Nimbostratus rankNimbostratus
      Just wanted to close the loop on this one in case anyone comes across this in the future. The 'http::header replace Host' was in fact replacing the host value, it was just the fact i was using the following statement to log this '[HTTP::host]:[HTTP::uri]' when in fact i should be using [HTTP::header values Host]. From my understanding the HTTP::host value would have still contained the original value. This rule is working fine with some additional tweaks for a few other conditions they wanted to check for and route based on.