Forum Discussion

Ube_34341's avatar
Ube_34341
Icon for Nimbostratus rankNimbostratus
Aug 02, 2013

Getting values of json from POST payload not working

Hi Guys,

 

strange behaviour down here. I'm trying to extract value of parameters from the payload of a POST and send with HSL using the below irule with no success at all: the variables are empty.

 

Can anyone tell me what's wrong with it?

 

 

when HTTP_REQUEST {

 

 

set hsl [HSL::open -proto UDP -pool HSL]

 

set uri [HTTP::uri]

 

set ip [IP::client_addr]

 

 

if {[HTTP::uri] contains "keepal"} {

 

set data [HTTP::payload]

 

set namevals [split [HTTP::payload] "&"]

 

set a 0

 

set b 0

 

set c 0

 

set d 0

 

for {set i 0} {$i < [llength $namevals]} {incr i} {

 

set params [split [lindex $namevals $i] "="]

 

if { [lindex $params 0] equals "parA" } {

 

set a [lindex $params 1]

 

}

 

if { [lindex $params 0] equals "parB" } {

 

set b [lindex $params 1]

 

}

 

if { [lindex $params 0] equals "parC" } {

 

set C [lindex $params 1]

 

}

 

if { [lindex $params 0] equals "parD" } {

 

set d [lindex $params 1]

 

}

 

}

 

HSL::send $hsl "$ip|$a|$b|$c|$d"

 

}

 

}

 

}

 

 

 

 

 

 

 

 

 

2 Replies

  • At a minimum you probably want to use the HTTP::collect command and HTTP_REQUEST_DATA event to capture the payload:

    
    when HTTP_REQUEST {
        if { ( [HTTP::method] equals "POST" ) and ( [string tolower [HTTP::uri]] contains "keepal" ) } {
            HTTP::collect [HTTP::header Content-Length]
        }
    }
    when HTTP_REQUEST_DATA {
        set payload [HTTP::payload]
         All collected payload is available here...
    
    }
    

    You're most likely not seeing the payload in the HTTP_REQUEST event because it exceeds a single TCP packet. Using HTTP::collect tells the iRule to collect and buffer the payload (up to the specified amount) and make it available in the HTTP_REQUEST_DATA event. Take a look at the wiki for both of these (command and event) for more thorough implementations.

  • e.g.

    [root@ve10:Active] config  b virtual bar list
    virtual bar {
       snat automap
       pool foo
       destination 172.28.19.252:80
       ip protocol 6
       rules myrule
       profiles {
          http {}
          tcp {}
       }
    }
    [root@ve10:Active] config  b rule myrule list
    rule myrule {
       when HTTP_REQUEST {
      if {[HTTP::method] eq "POST"}{
        if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576}{
          set content_length [HTTP::header "Content-Length"]
        } else {
            set content_length 1048576
        }
        if { $content_length > 0} {
          HTTP::collect $content_length
        }
      }
    }
    when HTTP_REQUEST_DATA {
      set a [URI::query "?&[HTTP::payload]" parA]
      set b [URI::query "?&[HTTP::payload]" parB]
      set c [URI::query "?&[HTTP::payload]" parC]
      set d [URI::query "?&[HTTP::payload]" parD]
      log local0. "a: $a b: $b c: $c d: $d"
    }
    }
    
    
     trace
    
    [root@ve10:Active] config  ssldump -Aed -nni 0.0 port 80
    New TCP connection 1: 172.28.20.17(50767) <-> 172.28.19.252(80)
    1375483782.1026 (0.0012)  C>S
    ---------------------------------------------------------------
    POST / HTTP/1.1
    User-Agent: curl/7.15.5 (i686-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
    Host: 172.28.19.252
    Accept: */*
    Content-Length: 38
    Content-Type: application/x-www-form-urlencoded
    
    parA=one&parB=two&parC=three&parD=four---------------------------------------------------------------
    
     /var/log/ltm
    
    [root@ve10:Active] config  cat /var/log/ltm
    Aug  3 06:49:42 local/tmm info tmm[5139]: Rule myrule : a: one b: two c: three d: four
    
    

    set hsl [HSL::open -proto UDP -pool HSL]

    just a small comment. i think hsl::open should be done in CLIENT_ACCEPTED.

    just my 2 cents.