Forum Discussion
iRule to change HTTP GET into POST
i have an incoming GET request on my virtual server which i want to change into a POST request towards the node. in princple this would mean:
- change the word GET into POST
- change the uri to remove the query part
- put the query string in the content
- add a Content-Length header
- possibly add a Content-Type header
but im getting stuck with turning the word GET into POST, this doesnt work: HTTP::method "POST" (error: [wrong args]), same with HTTP::request. i found this irule https://devcentral.f5.com/wiki/iRules.HTTP_mothod_conversion.ashx but it feels quite a lot of work and might not work looking at the comment. is this really so complicated or am i missing something?
- IheartF5_45022Nacreous
Hi I have managed to do this without using TCP::collect. I have borrowed the idea from this post https://devcentral.f5.com/codeshare/http-method-conversion, but without the need to use 2 separate virtual servers.
The following iRule will convert a GET request with query parameters into a POST to the same path, but placing the query parameters in the request body instead of the request line.
Be careful....you could exhaust all your connections on the box if you tinker with it and get it wrong 🙂
when HTTP_REQUEST { set pool [LB::server pool] set method [HTTP::method] if {[HTTP::uri] eq "/reentrant"} { HTTP::respond 200 return } elseif {[HTTP::method] eq "GET"} { Create POST set post "POST [HTTP::path] HTTP/1.1\r\nHost: [HTTP::host]\r\nContent-Type: text/plain\r\nContent-Length: [string length [URI::query [HTTP::uri]]]\r\n\r\n[URI::query [HTTP::uri]]" Change the uri so that when this event is fired again we know to return a 200 HTTP::uri "/reentrant" Invoke this iRule again re-entrantly virtual [virtual] } } when HTTP_RESPONSE { If the clientside request was a GET, retry as a POST if {$method eq "GET"} { pool $pool HTTP::retry $post return } }
- Kevin_StewartEmployee
The trick is that you have to do this in the TCP events (CLIENT_ACCEPTED and CLIENT_DATA) as the HTTP::method command is read-only. Here is a somewhat simple example of how this looks:
when CLIENT_ACCEPTED { TCP::collect } when CLIENT_DATA { separate uri and query string set uri [findstr [TCP::payload] "GET " 4 " HTTP/1."] set uri_no_query [findstr $uri "" 0 "?"] set query [findstr $uri "?" 1] replace TCP payload regsub -all -nocase "GET" [TCP::payload] "POST" newdata set newdata1 [string map "$uri $uri_no_query" $newdata] regsub -all -nocase "Accept: " $newdata1 "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: [string length $query]\r\nAccept: " newdata2 TCP::payload replace 0 [TCP::payload length] ${newdata2}$query TCP::release }
I first separate the URI from the query string, then perform a series of replace functions to 1) change GET to POST, change the original URI to the URI without query string, and 3) inserts the Content-Type and Content-Length headers before the Accept.
This is just an example, so it doesn't account for the following conditions:
- Whether or not the request is originally a GET or POST
- Whether or not Content-Type and Content-Length headers are already present
- Kevin_StewartEmployee
I can't speak for why HTTP::request and HTTP::method are read-only commands, but the overhead of doing this at layer 4 should be minimal if you filter the payload appropriately. You know that the TCP::payload of a GET request will start with;
GET /some-uri HTTP/1.
so simply issue a TCP::release if it's not what you're looking for.
By the way, if you're doing this with an HTTPS VIP, just change TCP:: to SSL:: and use the CLIENTSSL_HANDSHAKE and CLIENTSSL_DATA events.
This may or may not help, but I had a similar problem with a POST turning into a GET after a 302 redirect. Instead of converting the GET back into a POST with iRules, I simply issued HTTP::respond 307 Location "http://post.here.com"
302s cause browsers to convert the initial POST request into a GET. 307s tells the client to resubmit data as a post after a redirect. This saved me a lot of trouble.
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