I was looking today for a way to gracefully forward a POST request from one page to another in PHP. By “forwarding the request” I mean redirecting the user to another page on a different domain with all the POST data intact. I want to stress on the definition, because most people understand “use cURL to create a POST request from PHP”. Being on a different domain, it kind of rules out cookies and sessions.

The proper way to do it is by issuing a HTTP 307 – Temporary redirect header – which will instruct the browser to resend the data to the new URI, indicated by the Location field of the response.

PHP

1

2

header('HTTP/1.1 307 Temporary Redirect');

header('Location: new-location.php');

Just for the record, in pre-HTTP 1.1 browsers the POST data gets converted to GET, but if your users don’t use computers from the 90s, this won’t be a problem. And it works like a charm. In Chrome and Internet Explorer.

In Firefox and Opera, the browser will pop-up a dialog, informing the user that the data is being redirected to another page and asking the user’s permission to continue. Which is an extremely stupid standard behavior. Yes, it’s in the standard!

If the 307 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

…straight from the HTTP’s status codes bible, RFC 2616. Why do I say it’s a stupid specification? Because it is! It makes no sense to pop-up a dialog that might confuse the user when the data was already sent. For example, if I’m a malevolent webmaster, I already have the user’s data, so at this point displaying the dialog box is useless. I can save the data in my database and have a cronjob connect to the new page or do whatever I please with the POSTed information. However, if the redirect is legitimate, displaying the message box might confuse the user and have him cancel the request, which might break the application’s logic.

Great work guys, I’m moments away from converting the POST data into GET and send it in the URL…

Nice one. I had no idea POST requests could be forwarded with just a simple header. It reminds me of an issue with Apache where you POST data to http://example.org/location, and Apache issues a 301 redirect to http://example.org/location/ (notice the final slash). Because it’s a 301 response, it drops all POST data. I’ve scratched my head a couple of time because of this.

By the way, it seems the RFC specifies the same behaviour for both 301 and 307 responses with POST requests, but Firefox only shows the confirmation dialog with 307 responses.