Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
Clear all filters
Answers

How to preserve data in a HTTP 302 redirect of a POST

Hi,

We are trying to implement the following scenario and would like to know if the LTM can do the following:

  1. An application execute an HTTP POST request with parameters inside the HTML body
  2. LTM sends back a 302 redirect request back to the client to another local url

How can LTM sends back in the 302 redirect with the same parameters that were availble in the initial packet (see 1))?

Can LTM look into HTML body and use them in packet 2) with an iRule?

In initial packet 1) these parameters can be a small text or a large file that is being posted to the servers behind LTM

Thanks, Giulio.

0
Rate this Question

Answers to this Question

placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

What do the parameters in the body look like?

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Hi,

This is the initial packet with the POST DATA

https://dl.dropboxusercontent.com/u/11374616/first%20request.png

and this is the second, after the 302, with empty parameters

https://dl.dropboxusercontent.com/u/11374616/redirect%20without%20parameters.png

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Hi 2funky,

I normally step a bit back, and ask, why do we get the redirect ? Wouldn't it make sense, that if the user sends the post to a the wrong URL, that BIG-IP would change the inital Post to point to the right backend URL ?

ie: your post goes to www.test.com/login.php redirect sends you to www.test.com/prod/login.php Browser sends the request to www.test.com/prod/login.php (without Parameters) iRule would need to add it.

What you could do very easy would be to change the inital post www.test.com/login.php to www.test.com/prod/login.php without changing the Parameters. So the Backend System would not need to send a redirect, and could consume the Parameters and Values as needed.

Wiesmann

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Generally speaking, if you need to do a redirect and keep all post parameters, you will have to create a postback form which then has the client actually post to the new URL.

If the form that generates the POST is flowing through your LTM and you can't get the developers to update the target URL of the form, you may be able to use a stream replacement to change it on the way out of the LTM to the browser before they make the first post.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Hi,

Thanks for the answers. Indeed, we have a redirection iRule in place that we can not really change, as it is linked with GLB in case of servers unavailability.

So, if I get it well, LTM can parse HTML body and push it back the initial POST parameters inside the HTTP302? Do you have an example somewhere? Is it CPU intensive?

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

A 302 response is really nothing more that a simple message with a 302 status code and a Location header. That said, you could very easily send back arbitrary data in the 302 message in the payload or the URI. A browser would generally ignore the payload of a 302 response though, so it may make more sense, if the next server needs this information to either:

  1. Convert the POST payload to query string data and include in the Location URL, or

  2. Issue a 307 response instead, which will generally cause a browser to re-POST the data to the specified URL. Not all browsers treat a 307 the same way though, so mileage may vary.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

So, now I think this iRule should do what you require just need to set your redirect URL (including the URI)


0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
when RULE_INIT {
    set static::ext_url "http://host.header.com/path/login.php"
}
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 "?"       
    foreach p [split [HTTP::payload] &] {
        set name  [URI::decode [getfield $p = 1]]
        set value [URI::decode [getfield $p = 2]]
    set content "${content}$name=$value&"
    #log local0. "Content: $content"
    }
    set content "${content}"
    set where_to "$static::ext_url$content"
    #log local0. "$where_to"
}
when HTTP_RESPONSE {
    if { [info exists where_to] } {
        HTTP::respond 302 Location $where_to
    }
}
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Hello, I'm trying to use the code supplied by Juerg Wiesmann but am getting the following error:

[parse error: PARSE syntax 357 {syntax error in expression " [HTTP::header "Content-Length"] > 1048000 "
: variable references require preceding $}] [{ [HTTP::header "Content-Length"] > 1048000 }]

I have very basic F5 knowledge so this is all new to me. I'm on v11, any help appreciated!

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Think I sorted it, the copy/paste from web converted the greater than ">" symbol to ">".

Though whilst the F5 passed the syntax check, the rule broke the webservice :)

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Hello, I am facing similar challenge. I insert a new value to request header before redirect. seems that F5 drops the new value somehow.

HTTP::header insert "appKey" "$app_key" HTTP::redirect "https://$NewHost[HTTP::uri]"

if I log header into logs, I can see that appKey gets inserted. however when I check at NewHost, I see the request came in with no appKey value in the header.

in other cases when I had to do the same, it worked but there was no redirect. so I am certain that redirect has something to do with it. it's just wont let through any newly added name/value in request-header.

any idea how can I insert new name/value into request header and make redirect call right after ( without losing new added value).?

thank you in advance.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Jaz, use HTTP::respond instead.

HTTP::respond 302 Location "https://$NewHost[HTTP::uri]" "appKey" "$app_key"

This command allows you to insert an arbitrary set of headers (most important the "Location" header).

0