18

I'm trying to figure out how to redirect to a new page (different application, controller, action) and maintain the current POST data.

My app is validating the POST data and if a certain criteria is met, I want to redirect to a different location, but make sure the POST data is passed as POST data to that new page. Here's a rough example:

POST /app1/example HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
    var1=foo&var2=bar

In my exampleAction (Zend_Controller_Action), I check to see if var1 == foo, and if it does I want to redirect (302) to /app2/example with that same POST data. Something maybe like this?

HTTP/1.x 302 Found
Location: /app2/example
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
    var1=foo&var2=bar

I can see how to create a new HTTP request using Zend_Http_Client, but I'm not looking to simply request the page and display the content. Should I still be looking to use Zend_Http_Client anyway? At the moment I'm playing with stuff like this:

$this->getResponse()->setRedirect('/app2/example/', 302);
$this->getResponse()->setBody(http_build_query($this->_request->getPost()));

I'm sure what I want to do is possible through some means of trickery and demon-cavorting, but it's definitely alluding me. Any help is appreciated.

- rk

Charles
  • 50,943
  • 13
  • 104
  • 142
angrychimp
  • 696
  • 1
  • 6
  • 13

6 Answers6

16

Rather than redirecting the browser to the new location, why not just forward the request from the controller to the other controller?

return $this->_forward("action", "controller", "module");
gnarf
  • 105,192
  • 25
  • 127
  • 161
  • 1
    I tried that and it seems to lock the application. I'm not seeing any request activity (using LiveHTTPHeaders for Firefox) and my httpd thread just spikes the CPU (as viewed from top). I'll add some logging to the code to see if it's actually caught in an endless loop or not, because I'd really like this to be the answer. – angrychimp Aug 21 '09 at 01:15
  • Well - first of all - use set_time_limit(5) or something like that right before the call, so that php will break with an error after 5 seconds of execution time, you should be able to see the "loop" with a stack trace. Also, Its not going to make another HTTP request, the Dispatcher will just change the controller/module/action parameters in the Zend_Controller_Request and redispatch. If for some reason that other action is forwarding, or doing something strange that calls back to the original action you may be getting a loop. – gnarf Aug 21 '09 at 08:13
  • 1
    Well, it seems like would have been exactly what I wanted, except that for some reason we don't have our modules configured correctly. We've got some wacky set up where each module accessed is set up as the default module, and it's unaware of the other modules. Go figure. Thanks though for the verification, gnarf! – angrychimp Aug 21 '09 at 18:02
  • This does not answer the question. While you helped the one guy who asked, the 1000 guys after him come here and find your answer useless. Please answer the *question* - don't tell them they're asking the wrong question. – B T May 02 '13 at 03:08
13

IMO you can't do a Redirect with POST. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3

As already said you could save your POST-Data in the Session.

Benjamin Cremer
  • 4,842
  • 1
  • 24
  • 30
7

You can use a Controller _request object

$this->_request->setPost(array(
    'someKey' => 'someValue'
));

And then simply use _forward protected method

$this->_forward('yourAction', 'yourController', 'yourModule');

Then, in forwarded controller action just call

$aPost = $this->_request->getPost();
2

You can use the redirector action helper:

http://framework.zend.com/manual/1.12/en/zend.controller.actionhelpers.html#zend.controller.actionhelpers.redirector

This is working for me. It is passing the login credentials from one login screen to another. The 307 may cause the browser to alert the user that the redirect is occurring, a 303 will redirect and populate the credentials on the next page, but not submit the second form.

$baseUrl = 'https://example.com';
$this->_redirector = $this->_helper->getHelper('Redirector');
$this->_redirector->setCode(307)
   ->setUseAbsoluteUri(true)
   ->gotoUrl($baseUrl . '/home/login',
        array('username' => $authForm->getValue('username'),
              'password' => $authForm->getValue('password')
        )
   );
user2182349
  • 9,569
  • 3
  • 29
  • 41
0

Because the client handles the redirection after the server's response I don't think you can do much about this. Firefox for example asks the user whether he/she wants to resend the POST data to the new location or not.

A nasty solution would be to fill and return a HTML form and auto-submit it with JavaScript. :/

Philippe Gerber
  • 17,457
  • 6
  • 45
  • 40
0

I'm not too familiar with Zend specifically, but there are two approaches I'd take to your problem:

  1. Store the POST data in the session for the life of that request/redirect
  2. Set the redirect to be a POST, and encode the data. Instead of using redirect, just send a new header with POST instead of GET.
cam8001
  • 1,581
  • 1
  • 11
  • 22