Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

php with Curl: follow redirect with POST

I have a script that send POST data to several pages. however, I encountered some difficulties sending request to some servers. The reason is redirection. Here's the model:

  1. I'am sending post request to server
  2. Server responses: 301 Moved Permanently
  3. Then curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, TRUE) kicks in and follows the redirection (but via GET request).

To solve this I'am using curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, "POST") and yes, now its redirecting without POST body content that I've send in first request. How can I force curl to send post body when redirected? Thanks!

Here's the example:

<?php 
function curlPost($url, $postData = "")
{
    $ch = curl_init () or exit ( "curl error: Can't init curl" );
    $url = trim ( $url );
    curl_setopt ( $ch, CURLOPT_URL, $url );
    //curl_setopt ( $ch, CURLOPT_POST, 1 );
    curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt ( $ch, CURLOPT_POSTFIELDS, $postData );
    curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt ( $ch, CURLOPT_CONNECTTIMEOUT, 30 );
    curl_setopt ( $ch, CURLOPT_TIMEOUT, 30 );
    curl_setopt ( $ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36");
    curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, TRUE);

    $response = curl_exec ( $ch );
    if (! $response) {
        echo "Curl errno: " . curl_errno ( $ch ) . " (" . $url . " postdata = $postData )\n";
        echo "Curl error: " . curl_error ( $ch ) . " (" . $url . " postdata = $postData )\n";
        $info = curl_getinfo($ch);
        echo "HTTP code: ".$info["http_code"]."\n";
        // exit();
    }
    curl_close ( $ch );
    // echo $response;
    return $response;
}
?>
like image 548
Александр Пушкин Avatar asked Feb 12 '16 10:02

Александр Пушкин


1 Answers

curl is following what RFC 7231 suggests, which also is what browsers typically do for 301 responses:

  Note: For historical reasons, a user agent MAY change the request
  method from POST to GET for the subsequent request.  If this
  behavior is undesired, the 307 (Temporary Redirect) status code
  can be used instead.

If you think that's undesirable, you can change it with the CURLOPT_POSTREDIR option, which only seems very sparsely documented in PHP but the libcurl docs explains it. By setting the correct bitmask there, you then make curl not change method when it follows the redirect.

If you control the server end for this, an easier fix would be to make sure a 307 response code is returned instead of a 301.

like image 83
Daniel Stenberg Avatar answered Oct 20 '22 14:10

Daniel Stenberg