Forum Discussion
irule: reading HTTP body in POST
Hi, i'm new to the forum, i'm trying to design an irule to do the something like below:
When HTTP_REQUEST{
if
{ ([string tolower [HTTP::uri]] contains "type") || ([string tolower [HTTP::uri]] contains "value") }
{ HTTP::close }
elseif
{ (HTTP::body contains “"name": "account-id"”) || (HTTP::body contains “"name": "account-number"”) }
{ HTTP::close }
}
I'd be grateful if someone could help me find the right syntax to do this in irule? I've looked for a while in vain. Do i need to capture a payload first before i can inspect the body of a POST?
Cheers
3 Replies
- Kevin_Stewart
Employee
A POST is a request method. Do you need to capture a request from the client or a response from the server? - Didier_123836
Nimbostratus
I need to capture a request from the client. This is basically like implementing a black-list for some parameters.. - Kevin_Stewart
Employee
There are several ways to do this. The samples below are just two abstracts for evaluating the payload of a request (and/or response).
HTTP::collect method
when HTTP_REQUEST { if { [HTTP::method] eq "POST" } { Trigger the collection for up to 1MB of data if { [HTTP::header Content-Length] ne "" and [HTTP::header value Content-Length] <= 1048576 } { set content_length [HTTP::header value 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 { Do stuff with the payload set payload [HTTP::payload] log local0. $payload }In this example you're going to collect the request payload if the request method is a POST. The good thing about this method is that you can evaluate the entire payload. The bad thing is that this method can consume a lot of processing if the payloads are large. Notice in the HTTP_REQUEST event that the payload length has been limited to 1mb. If the values that you're looking for are beyond that, then you have to increase this value at the possible expense of processing cycles. Once inside the HTTP_REQUEST_DATA event, the payload of the request is available via HTTP::payload. There are also instances where the payload may traverse multiple requests, because of the size of the request. This isn't too common, but if it happens you'll need to issue additional HTTP::collect events INSIDE the HTTP_REQUEST_DATA event.
STREAM method
==========================
when HTTP_REQUEST { STREAM::disable if { [HTTP::method] equals "POST" } { STREAM::expression "@user=\[^&\]+?@@ @password=\[^&\]+?@@" STREAM::enable } } when STREAM_MATCHED { log local0. [STREAM::match] STREAM::replace [STREAM::match] }==========================
In this method you're using a generic STREAM profile to filter on specific values within the payload (also if it's a POST request). The benefit of this approach is that it's VERY fast and not constrained by the size of the payload. The down side is that you have to be very explicit about what you're looking for. In the above example I've defined an explicit STREAM expression: "@user=\[^&\]+?@@ @password=\[^&\]+?@@" that is looking for two values. Essentially it says, anything that starts with "user=" or "password=" and terminates with an ampersand (&) character. If the STREAM profile sees either of these it'll fire the STREAM_MATCHED event and expose the match in STREAM::match. From that point you can replace or remove the content, terminate the connection, or whatever else you need.
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com