HTTP POST redirect preserving POST data
Problem this snippet solves:
Use Javascript in an iRule to redirect HTTP POST requests to HTTPS. When an HTTP 30x redirect it sent to a client that has sent a POST request, the user-agent transparently issues a new GET request. As a result, the original POST request payload is lost.
The idea behind this iRule is when client sends a POST to an HTTP virtual server, LTM replies with an HTML page which contains a form. The form contains post-data that the client just sent. The form will be auto-submitted by Javascript via HTTPS.
Here is how this iRule works:
- if method = post, it issues HTTP::collect, which will invoke HTTP_REQUEST_DATA
-
then it scans POST-data and prepares new content to respond to client. the new content will include
- form with all INPUT field names retrieved from POST-data
- the "action" parameter in the form points to external server
- all input fields are set as hidden (so client won't see the data during the process)
- Javascript that submits the form automatically
- then iRule replies to client with HTTP::respond command with content prepared in step 2
Code :
when RULE_INIT { set static::ext_url "https://10.10.71.3/test.post" } when HTTP_REQUEST { # Check if request was a POST if { [string tolower [HTTP::method]] eq "post" } { # Check if there is a Content-Length header if { [HTTP::header exists "Content-Length"] } { if { [HTTP::header "Content-Length"] > 1048000 }{ # Content-Length over 1Mb so collect 1Mb set content_length 1048000 } else { # Content-Length under 1Mb so collect actual length set content_length [HTTP::header "Content-Length"] } } else { # Response did not have Content-Length header, so use default of 1Mb set content_length 1048000 } # Don't collect content if Content-Length header value was 0 if { $content_length > 0 } { HTTP::collect $content_length } } } when HTTP_REQUEST_DATA { set content "< script type=text/javascript language=javascript> \ function s(){ document.f.submit(); } \" HTTP::respond 200 content $content }
- Victor_PlohodNimbostratus
Hello, I'm trying to use your code on a VS where I configured https://devcentral.f5.com/s/articles/redirect-non-ssl-requests-on-ssl-virtual-server-rule I'm a noob in the irule world. 1. What is the role of ext_url "; . 2. Should I merge the code into one irule or apply two distinct irules on the VS
 
- Stanislas_Piro2Cumulonimbus
Hi,
A 307 status code is created to ask the client to preserve the method and the content on the new location
- Stanislas_Piro2Cumulonimbus
@victor Plohod, try this irule
when HTTP_REQUEST { Check if the client used an SSL cipher if {not ([catch {SSL::cipher version} result]) && [string tolower $result] ne "none"}{ Client did use a cipher log local0. "\$result: $result. Allowing encrypted request." } else { Client did not use a cipher log local0. "\$result: $result. Redirecting unencrypted request." if { [HTTP::method] eq "POST" } { HTTP::respond 307 "https://[HTTP::host]/" } else { HTTP::respond 302 "https://[HTTP::host]/" } } }
- Chris_BaiocchetNimbostratus
Hello,
Am curios about the statement:
set static::ext_url ";
is test.post generic and able to be used anywhere, or would I need to replace it with an entry specific to my environment?
Thanks in advance,
Chris