HTTP method conversion
Problem this snippet solves:
This is one way that allows you to convert HTTP method from GET to POST or POST to GET transparently by LTM.
Why?
- you want to hide something from users. (make it simpler for them)
- create meta proxy that also proxy auth and does auto-logon (or limited SSO)
- I don't know. I think it is fun.
What technique are used here?
- vip targeting vip
- HTTP::retry
- HTTP::respond
How does it work?
- configure 2 virtual servers one for normal HTTP load balance and another one to receive http request from virtual www1 and return back converted request. For example virtual www1 listens on 10.10.10.10:80 and point to pool webpool. Virtual www2 listen on 10.10.10.10:81 and has no pool assigned.
- virtual www1 receives http request from external clients and send selected request to virtual www2
- virtual www2 converts http request (for GET-to-POST, turn GET uri query string to POST data and for POST-to-GET, turn POST data to GET uri query string)
- virtual www2 responds back with "converted request" as its content
- virtual www1 receives HTTP_RESPONSE and do HTTP::retry with this "converted request"
Note: * This iRule is not perfect. It needs more development if you would like to use it. Feel free to put comment.
Code :
# rule for virtual www1 when HTTP_REQUEST { log local0. "[HTTP::request]" # send httprequest which you want to convert to another virtual # if [HTTP::uri] match what I want virtual www2 # else do nothing } when HTTP_RESPONSE { # use special status and/or remote_addr to identify # whether it comes back from real server or virtual www2 if { [HTTP::status] == 555 } { HTTP::collect [HTTP::header Content-Length] set reselect 1 } } when HTTP_RESPONSE_DATA { # probably add routine to verify # send converted http_request to real server log local0. "[HTTP::payload]" HTTP::retry [HTTP::payload] } when LB_SELECTED { # if http_retry is called, same destination may be picked (which is virtual www2) # change the destination to real server (use node or pool command) if { [info exists reselect ] } { LB::reselect node 10.10.72.1 80 unset reselect } log local0. "[LB::server]" } # rule for virtual www2 when HTTP_REQUEST { switch [HTTP::method] { GET { log local0. "uri = [HTTP::uri]" log local0. "query = [HTTP::query]" set query [HTTP::query] # strip off query string HTTP::uri [HTTP::path] # add Content-Type and Content-Length header HTTP::header insert Content-Type "application/x-www-form-urlencoded" HTTP::header insert "Content-Length" [string length $query] # strip off "GET " set request [substr [HTTP::request] 4] # create new request starts with POST # follow by original header (with modified uri) # and POST data (derived from query string) # according to http encoding, some characters may need attention # for example, space is %20 in GET uri but + in POST data HTTP::respond 555 content "POST $request$query" } POST { log local0. "len = [HTTP::header Content-Length]" log local0. "req = [HTTP::request]" # collect POST data HTTP::collect [HTTP::header Content-Length] } } } when HTTP_REQUEST_DATA { # prepare GET uri query string set query [HTTP::payload] # according to http encoding, some characters may need attention # for example, space is %20 in GET uri but + in POST data HTTP::uri "[HTTP::uri]?$query" # we don't need Content-Type and Content-Length anymore HTTP::header remove Content-Type HTTP::header remove Content-Length # remove POST data HTTP::payload replace 0 [HTTP::payload length] "" # strip off "POST " set request [substr [HTTP::request] 5] HTTP::respond 555 content "GET $request" }
Published Mar 18, 2015
Version 1.0Nat_Thirasuttakorn
Employee
Joined September 25, 2004
Nat_Thirasuttakorn
Employee
Joined September 25, 2004
- IheartF5_45022NacreousHi there. Thanks for the idea for this - I've managed to streamline this into a single virtual/iRule and the code is here https://devcentral.f5.com/s/feed/0D51T00006j2lHBSAY at the bottom, but it's based on my reading this post.
- Przemyslaw_Wyr1Altocumulus
Hi There. The link does not works