Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Curl POST is executed as a GET

I'm trying to develop a kind of Browser with PHP. So far my class can process a GET or a POST request with this Content Type: application/x-www-form-urlencoded.

Now I need to move to a JSON one. I've set the Content-Type header to application/json.

The fact is, with this type I got the following issue: Setting up a POST request will result in a GET request. This is really weird.

Here is my code:

private function request($url, $reset_cookies, $post_data = null, $custom_headers = null)
{       
    // Create options
    $options = array(
        CURLOPT_URL               => $url,
        CURLOPT_RETURNTRANSFER    => 1,
        CURLOPT_HEADER            => 0,
        CURLINFO_HEADER_OUT       => 1,
        CURLOPT_FAILONERROR       => 1,
        CURLOPT_USERAGENT         => $this->user_agent,
        CURLOPT_CONNECTTIMEOUT    => 30,
        CURLOPT_TIMEOUT           => 30,
        CURLOPT_FOLLOWLOCATION    => 1,
        CURLOPT_MAXREDIRS         => 10,
        CURLOPT_AUTOREFERER       => 1,
        CURLOPT_COOKIESESSION     => $reset_cookies ? 1 : 0,
        CURLOPT_COOKIEJAR         => $this->cookies_file,
        CURLOPT_COOKIEFILE        => $this->cookies_file,
        CURLOPT_HTTPHEADER        => array('Accept-language: en'),

        // SSL
        /*
        CURLOPT_SSL_CIPHER_LIST   => 'TLSv1',
        CURLOPT_SSL_VERIFYPEER    => 1,
        CURLOPT_CAINFO            => dirname(__FILE__) . '/Entrust.netCertificationAuthority(2048).crt',
        */
    );

    // Add headers
    if (isset($custom_headers)) $options[CURLOPT_HTTPHEADER] = array_merge($options[CURLOPT_HTTPHEADER], $custom_headers);

    // Add POST data
    if (isset($post_data))
    {
        $options[CURLOPT_POST]          = 1;
        $options[CURLOPT_POSTFIELDS]    = is_string($post_data) ? $post_data : http_build_query($post_data);
    }

    // Attach options
    curl_setopt_array($this->curl, $options);

    // Execute the request and read the response
    $content = curl_exec($this->curl);

    print_r($options);
    print_r(curl_getinfo($this->curl, CURLINFO_HEADER_OUT));

    // Clean local variables
    unset($url);
    unset($reset_cookies);
    unset($post_data);
    unset($custom_headers);
    unset($options);

    // Handle any error
    if (curl_errno($this->curl))
    {
        unset($content);
        throw new Exception(curl_error($this->curl));
    }

    return $content;
}

To illustrate my issue, here is an example:

CUrl options as an Array:

Array
(
    [10002] => http://mywebsite.com/post/
    [19913] => 1
    [42] => 0
    [2] => 1
    [45] => 1
    [10018] => Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
    [78] => 30
    [13] => 30
    [52] => 1
    [68] => 10
    [58] => 1
    [96] => 0
    [10082] => C:\wamp\www\v2\_libs/../_cookies/14d0fd2b-9f15-4ac5-8fae-4246cc6cef49.cookie
    [10031] => C:\wamp\www\v2\_libs/../_cookies/14d0fd2b-9f15-4ac5-8fae-4246cc6cef49.cookie
    [10023] => Array
        (
            [0] => Accept-language: en
            [1] => RequestVerificationToken: 4PMxvJsQzFJ5oFt3JdUPe6Bp_geIj4obDJCYIRoU09PrrfcBSUgJT9iB3mXnGFc2KSlYrPcRHF7iHdQhGNu0GKLUzd5FywfaADbGS8wjhXraF36W0
            [2] => Content-Type: application/json
        )

    [47] => 1
    [10015] => {"usernameOrFeedId":"manitoba","feed_message_body":"Dummy message goes here"}
)

So the request header seems good to me, but I may be wrong.

And here is the real header sent by CUrl:

GET /post/ HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Host: mywebsite.com
Accept: */*
Referer: http://mywebsite.com/post/
Cookie: ADRUM_BT=R%3a53%7cclientRequestGUID%3a9787a51b-b24d-4400-9d6a-efbd618c74c0%7cbtId%3a18790%7cbtERT%3a44; CSRFToken=o_eoIVji7pWclOsrLaJpZEbOFSBJBm851rHbH0Xqwdzw2tC5j07EAc23mlj-opWowgpj0RkHyiktl1cS6onBqI43afM1; WebSessionId=3aem0m2xpwmvesgphna5gaop; prod=rd101o00000000000000000000ffff0a5a2a74o80; AuthenticateCookie=AAAAAtsQgeb8+UXrJ+wa7CGVJKnqizEAo2bMuFvqvwYMAl1NRaa6z68LBRx9hiHzPBC8tYqiayHID6pHChGXB7VywemwTpGivcRQ3nRlUVuaYQKyxQt21p1mx7OMlLCsRA==; web_lang.prod=fr
Accept-language: en
RequestVerificationToken: 4PMxvJsQzFJ5oFt3JdUPe6Bp_geIj4obDJCYIRoU09PrrfcBSUgJT9iB3mXnGFc2KSlYrPcRHF7iHdQhGNu0GKLUzd5FywfaADbGS8wjhXraF34W0
Content-Type: application/json

As you can see, it's a GET request and the post data look to have disapeared.

Am I doing it wrong ?

like image 451
Manitoba Avatar asked Mar 16 '23 04:03

Manitoba


2 Answers

You're following redirects, that means you get a 3xx response code and curl makes a second request to the new URL.

curl will act according to the specific 3xx code and for some of the redirects it will change request method from POST to GET - enabling VERBOSE will show you if it does so or not. The response codes that makes curl change method are 301, 302 and 303. It does so because that's how browsers act on those response codes.

libcurl offers an option called CURLOPT_POSTREDIR that you can use to tell curl to not change method for specific HTTP responses. Using that, you can thus have curl send a POST even after redirecting with one of these response codes.

like image 70
Daniel Stenberg Avatar answered Mar 27 '23 10:03

Daniel Stenberg


CURLOPT_FOLLOWLOCATION

seems to be the cause shown by

Referer: http://mywebsite.com/post/

seems the server is doing a PRG ?

http://en.wikipedia.org/wiki/Post/Redirect/Get

like image 29
exussum Avatar answered Mar 27 '23 12:03

exussum