Forum Discussion

Jean-Christoph8's avatar
Jean-Christoph8
Icon for Nimbostratus rankNimbostratus
Jan 13, 2014

Irules to do URI mapping from a HTTP POST request

Hello,

We are working with a search engine that is sending HTTP queries to its search engines via HTTP POST requests. I need to setup an irule that has to do URI mapping based on some HTTP parameters sent via this POST requests. Because it's a POST and not a GET request, I can't user HTTP::uri to analyze the parameters and do the URI mapping to forward the HTTP request to the correct pool.

The following irule is working with HTTP GET but not HTTP POST. Do you have any idea how to convert this irule to be compliant with a POST request ? Thanks in advance for any support.

JC

 

when HTTP_REQUEST { 
    set DEBUG 0
     Workaround: BIG IP Cache limitation for huge URI
     -----------------------------------------------
        if { [string length [HTTP::uri]] >= 16384} {
             WAM::disable
    }   
    set uri [string tolower [HTTP::uri]]

     Rewrite only URI starting with /action= or /?action=
     -----------------------------------------------
    if { $uri contains "action=" } {

         URI::query works only if the Query String starts with a '?'
         so we add a ? in front of the Query String if needed
         ----------------------------------------------
        if { not ([HTTP::uri] starts_with "/?") } {
            set uri [string replace $uri 0 0 "?"] 
        }

         Extract from URI the value of the following parameters:
         MatchLanguage
         action
         DatabaseMatch
         -----------------------------------------------
        set matchlanguage_value [URI::query $uri matchlanguage]
        set action_value [URI::query $uri action]
        set db_value [URI::query $uri databasematch]

         ------------------  
        if { $DEBUG > 0 } { 
            log local0. "MatchLanguage value=$matchlanguage_value"  
            log local0. "Action value=$action_value" 
            log local0. "DatabaseMatch value=$db_value" 
        }

         Rewrite URI for content servers only for the 3 types of actions otherwise default to proxy:
         getquerytagvalues
         query
         termexpand
         -------------------------------------------------------------------------------------------
        if { $action_value eq "getquerytagvalues" or $action_value eq "query" or $action_value eq "termexpand" } {

             Remember original URI before rewriting
             to keep the ability to do a rollback in case we will find an "unknown" language
             -------------------------------------------------------------------
            set original_query [HTTP::uri]
            set uri [HTTP::uri]

             Rewrite URI  : replace .._Elx with Elx where .. match 2 chars
             ---------------------------------------
            regsub -all ".._Elx" $uri "Elx" uri
            HTTP::uri $uri

            if { $DEBUG > 1 } { 
                log local0. "Before URI rewrite : $original_query" 
                log local0. "After URI rewrite : $uri"  
            }

             Depending on MatchLanguage parameter found in the URL
             Select the corresponding pool in charge of the language
             If language is not in the lits, rollback to original URI and 
             send the query to the IDOL proxies
             --------------------------------------------------------
            switch $matchlanguage_value {   
                "english" { set selected_pool "idol-en-content-test-pool1" }
                "french" { set selected_pool "idol-fr-content-test-pool1" }
                "german" { set selected_pool "idol-de-content-test-pool1" }
                "czech" { set selected_pool "idol-cs-content-test-pool1" }
                "bulgarian" { set selected_pool "idol-bg-content-test-pool1" }
                "croatian" { set selected_pool "idol-hr-content-test-pool1" }
                "czech" { set selected_pool "idol-cs-content-test-pool1" }
                "danish" { set selected_pool "idol-da-content-test-pool1" }
                "dutch" { set selected_pool "idol-nl-content-test-pool1" }
                "estonian" { set selected_pool "idol-et-content-test-pool1" }
                "finnish" { set selected_pool "idol-fi-content-test-pool1" }
                "gaelic" { set selected_pool "idol-ga-content-test-pool1" }
                "greek" { set selected_pool "idol-el-content-test-pool1" }
                "hungarian" { set selected_pool "idol-hu-content-test-pool1" }
                "italian" { set selected_pool "idol-it-content-test-pool1" }
                "latvian" { set selected_pool "idol-lv-content-test-pool1" }
                "lithuanian" { set selected_pool "idol-lt-content-test-pool1" }
                "maltese" { set selected_pool "idol-mt-content-test-pool1" }
                "portuguese" { set selected_pool "idol-pt-content-test-pool1" }
                "romanian" { set selected_pool "idol-ro-content-test-pool1" }
                "slovak" { set selected_pool "idol-sk-content-test-pool1" }
                "slovenian" { set selected_pool "idol-sl-content-test-pool1" }
                "spanish" { set selected_pool "idol-es-content-test-pool1" }
                "swedish" { set selected_pool "idol-sv-content-test-pool1" }
                "norwegian" { set selected_pool "idol-no-content-test-pool1" }
                "icelandic" { set selected_pool "idol-is-content-test-pool1" }
                default {
                    if { $DEBUG > 0 } { log local0. "matchlanguage not found : roll back to idol-proxy-test-pool1" }
                    HTTP::uri $original_query
                    set selected_pool "idol-proxy-test-pool1" 
                }
            }

            if { $DEBUG > 0 } { 
                    log local0. "Selected Pool=$selected_pool , MatchLanguage=$matchlanguage_value, Action=$action_value" 
            }

             Send the HTTP request to the previously selected pool
             -------------------------------------------
            pool $selected_pool
        }
    } 
}

 

3 Replies

  • Arie's avatar
    Arie
    Icon for Altostratus rankAltostratus

    In a POST request the values are stored in the body of the request. You'll want to use HTTP::collect / HTTP::payload to examine the body.

     

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

     

  • Thanks Arie for this tip.

    Now, I'm able to parse the value from the body and I'm able to determine the correct pool ($selected_pool).

    But I'm a bit lost now because I have to do some rewriting on this value before submiting the POST data to this selected pool.

    I don't know how to do this "properly". I'm a bit lost.

    Thanks again for your help.

    JC

    The new version of my irule is now the following:

     

         Collect a request payload
    when HTTP_REQUEST {  
          if {[HTTP::method] eq "POST"}{
             Trigger collection for up to 1MB of data
            if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576}{
              set content_length [HTTP::header "Content-Length"]
            } else {
                set content_length 1048576
            }
             Check if $content_length is not set to 0
            if { $content_length > 0} {
              HTTP::collect $content_length
            }
          }
    }
    
    
    when HTTP_REQUEST_DATA {    
        set DEBUG 0
    
        set original_query [HTTP::payload]
        set uri [string tolower $original_query]
    
         Workaround: BIG IP Cache limitation for huge URI
         -----------------------------------------------
            if { [string length $uri] >= 16384} {
                 WAM::disable
            } 
    
         Rewrite only URI of type /action= or /?action=
         -----------------------------------------------
        if { $uri contains "action=" } {
    
             URI::query works only if the Query String starts with a '?'
             so we add a ? in front of the Query String if needed
             ----------------------------------------------
            if { not ($uri starts_with "/?") } {
                set uri "?$uri" 
            }
    
             Extract from URI the value of the following parameters:
             MatchLanguage
             action
             DatabaseMatch
             -----------------------------------------------
            set matchlanguage_value [URI::query $uri matchlanguage]
            set action_value [URI::query $uri action]
            set db_value [URI::query $uri databasematch]
    
             ------------------  
            if { $DEBUG > 0 } { 
                log local0. "MatchLanguage value=$matchlanguage_value"  
                log local0. "Action value=$action_value" 
                log local0. "DatabaseMatch value=$db_value" 
            }
    
             Rewrite URI for content servers only for the 3 types of actions otherwise default to proxy:
             getquerytagvalues
             query
             termexpand
             -------------------------------------------------------------------------------------------
            if { $action_value eq "getquerytagvalues" or $action_value eq "query" or $action_value eq "termexpand" } {
    
                 Rollback to original Query with the upper and lower case
                 -------------------------------------------------------------------
                set uri $original_query
    
                 Rewrite URI  : replace .._Elx with Elx where .. match 2 chars
                 ---------------------------------------
                regsub -all ".._Elx" $uri "Elx" uri
                HTTP::uri $uri
    
                if { $DEBUG > 1 } { 
                    log local0. "Before URI rewrite : $original_query" 
                    log local0. "After URI rewrite : $uri"  
                }
    
                 Depending on MatchLanguage parameter found in the URL
                 Select the corresponding pool in charge of the language
                 If language is not in the lits, rollback to original URI and 
                 send the query to the IDOL proxies
                 --------------------------------------------------------
                switch $matchlanguage_value {   
                    "english" { set selected_pool "idol-en-content-reception-pool1" }
                    "french" { set selected_pool "idol-fr-content-reception-pool1" }
                    "german" { set selected_pool "idol-de-content-reception-pool1" }
                    "czech" { set selected_pool "idol-cs-content-reception-pool1" }
                    "bulgarian" { set selected_pool "idol-bg-content-reception-pool1" }
                    "croatian" { set selected_pool "idol-hr-content-reception-pool1" }
                    "czech" { set selected_pool "idol-cs-content-reception-pool1" }
                    "danish" { set selected_pool "idol-da-content-reception-pool1" }
                    "dutch" { set selected_pool "idol-nl-content-reception-pool1" }
                    "estonian" { set selected_pool "idol-et-content-reception-pool1" }
                    "finnish" { set selected_pool "idol-fi-content-reception-pool1" }
                    "gaelic" { set selected_pool "idol-ga-content-reception-pool1" }
                    "greek" { set selected_pool "idol-el-content-reception-pool1" }
                    "hungarian" { set selected_pool "idol-hu-content-reception-pool1" }
                    "italian" { set selected_pool "idol-it-content-reception-pool1" }
                    "latvian" { set selected_pool "idol-lv-content-reception-pool1" }
                    "lithuanian" { set selected_pool "idol-lt-content-reception-pool1" }
                    "maltese" { set selected_pool "idol-mt-content-reception-pool1" }
                    "portuguese" { set selected_pool "idol-pt-content-reception-pool1" }
                    "romanian" { set selected_pool "idol-ro-content-reception-pool1" }
                    "slovak" { set selected_pool "idol-sk-content-reception-pool1" }
                    "slovenian" { set selected_pool "idol-sl-content-reception-pool1" }
                    "spanish" { set selected_pool "idol-es-content-reception-pool1" }
                    "swedish" { set selected_pool "idol-sv-content-reception-pool1" }
                    "norwegian" { set selected_pool "idol-no-content-reception-pool1" }
                    "icelandic" { set selected_pool "idol-is-content-reception-pool1" }
                    default {
                        if { $DEBUG > 0 } { log local0. "matchlanguage not found : roll back to idol-proxy-reception-pool1" }
                        HTTP::uri $original_query
                        set selected_pool "idol-proxy-reception-pool1" 
                    }
                }
    
                if { $DEBUG > 0 } { 
                        log local0. "Selected Pool=$selected_pool , MatchLanguage=$matchlanguage_value, Action=$action_value" 
                }
    
                 Send the HTTP request to the previously selected pool
                 -------------------------------------------
                pool $selected_pool
            }
        } else {
            log local0. "Action not found in query : $uri"
        }
    }
    

     

    • Jean-Christoph8's avatar
      Jean-Christoph8
      Icon for Nimbostratus rankNimbostratus
      Hi, in other words: 1 - which instruction should I use to modify the data which was in the body of the request and resubmit it as a POST request ? 2 - Based on the content of the data in the body, which instruction should I use to submit my POST request to the correct pool ? Thanks a lot for your help JC