Forum Discussion

NoamRotter's avatar
NoamRotter
Icon for Altostratus rankAltostratus
Apr 26, 2020

Extract value from json

Hi,

I have a webapp which accepts a POST with JSON payload.

the JSON has only one key:value

I need to write to log the value of the key.

For example:

This is the payload of the JSON:

{ 
    "token": "c71c56b0-7590-4785-b490-0f060c563aee" 
} 

I need to write to the LTM log:

c71c56b0-7590-4785-b490-0f060c563aee

I need a simple iRule which parses the payload, find the value of "token" and writes it to the ltm log.

Can someone help please?

Noam.

  • Great! HTTP::payload must be able to retrieve it because it comes in a single packet so it doesn't need to accumulate. Note that if the payload was larger ( eg 1K ) then this might fail and you'd have to use HTTP::collect.

    We can use regexp in multiple ways to retrieve the substring. Try this:

    when HTTP_REQUEST {
      if { [HTTP::method] == "POST"} {
        log local0. ">>> Method is POST<<<"
        if {  [ regexp -- {"token": "(.+)"} [HTTP::payload] a b ] } {
            log local0.debug "Token Found a:$a b:$b"
        }
      }
    }

    $a should be the whole of the line, $b should be only the token part.

    Take a look here for more detail on how to use regexp:

    PS the other way we could have done it is this:

    set token [lindex [ regexp -inline -- {"token": "(.+)"} [HTTP::payload] ] 1]
  • when HTTP_REQUEST {
      if { [HTTP::method] == "POST"} {
        HTTP::collect
      }
    }
    when HTTP_REQUEST_DATA {
      set token [ regexp -inline -- {"token": "(.+)"} [HTTP::payload] ]
      log local0.debug "Token: $token" 
    }

    Try the above - I haven't tested it out but it looks ok

    • NoamRotter's avatar
      NoamRotter
      Icon for Altostratus rankAltostratus

      Hi Pete,

      Thank you for your answer.

      I tested your iRule.

      When using postman to post the JSON,

      the postman keeps saying "Sending Request" until I hit the cancel button

      I have added 2 logs line:

      when HTTP_REQUEST {
        if { [HTTP::method] == "POST"} {
        log local0. ">>> Method is POST<<<"
      	HTTP::collect
          log local0. ">>> HTTP Collected<<<"
        }
      }
      when HTTP_REQUEST_DATA {
        set token [ regexp -inline -- {"token": "(.+)"} [HTTP::payload] ]
        log local0.debug "Token: $token" 
      }

      In the ltm log I see:

      Apr 29 08:27:43 bigip1 info tmm2[18399]: Rule /Common/test-iRule <HTTP_REQUEST>: >>> Method is POST<<<

      Apr 29 08:27:43 bigip1 info tmm2[18399]: Rule /Common/test-iRule <HTTP_REQUEST>: >>> HTTP Collected<<<

      When I disable the HTTP::collect line

      Postman sends the request and finishes. Does not keep saying "Sending request"

      But, the when HTTP_REQUEST_DATA part is not executed.

      I moved these lines to HTTP_REQUEST part:

      set token [ regexp -inline -- {"token": "(.+)"} [HTTP::payload] ]

      log local0.debug "Token: $token"

      like this:

      when HTTP_REQUEST {
        if { [HTTP::method] == "POST"} {
          log local0. ">>> Method is POST<<<"
          set token [ regexp -inline -- {"token": "(.+)"} [HTTP::payload] ]
          log local0.debug "Token: $token" 
        }
      }

      And now I get in the ltm log:

      Apr 29 08:33:45 bigip1 debug tmm2[18399]: Rule /Common/test-iRule <HTTP_REQUEST>: Token: {"token": "01593317-66f9-4e8a-8467-6f4652e680e3"} 01593317-66f9-4e8a-8467-6f4652e680e3

      And I expected to get:

      Apr 29 08:33:45 bigip1 debug tmm2[18399]: Rule /Common/test-iRule <HTTP_REQUEST>: Token: 01593317-66f9-4e8a-8467-6f4652e680e3

      Thank you for your time.

      Noam.

  • Great! HTTP::payload must be able to retrieve it because it comes in a single packet so it doesn't need to accumulate. Note that if the payload was larger ( eg 1K ) then this might fail and you'd have to use HTTP::collect.

    We can use regexp in multiple ways to retrieve the substring. Try this:

    when HTTP_REQUEST {
      if { [HTTP::method] == "POST"} {
        log local0. ">>> Method is POST<<<"
        if {  [ regexp -- {"token": "(.+)"} [HTTP::payload] a b ] } {
            log local0.debug "Token Found a:$a b:$b"
        }
      }
    }

    $a should be the whole of the line, $b should be only the token part.

    Take a look here for more detail on how to use regexp:

    PS the other way we could have done it is this:

    set token [lindex [ regexp -inline -- {"token": "(.+)"} [HTTP::payload] ] 1]
    • NoamRotter's avatar
      NoamRotter
      Icon for Altostratus rankAltostratus

      Hi Pete,

      Thank you very much,

      This is working as well as the PS.

      👍