Inconsistencies between wp_remote_post and cURL

I can successfully make the RESTful post using cURL:

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://api.mindbodyonline.com/public/v6/usertoken/issue');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, {\n    \Username\: \Siteowner\,\n    \Password\: \apitest1234\\n});

$headers = array();
$headers[] = 'Content-Type: application/json';
$headers[] = 'Api-Key: {myapikey}';
$headers[] = 'Siteid: 999999';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$response = curl_exec($ch);
print_r($response);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

However, what seems to be the same request using wp_remote_post, fails to deliver the Api-Key in the headers:

$headers = array();
$headers[] = 'Content-Type: application/json';
$headers[] = 'Api-Key: {myapikey}';
$headers[] = 'Siteid: 999999';

$response = wp_remote_post( 'https://api.mindbodyonline.com/public/v6/usertoken/issue', array(
    'method' = 'POST',
    'timeout' = 45,
    'redirection' = 5,
    'httpversion' = '1.0',
    'blocking' = true,
    'headers' = $headers,
    'body' = array( 'Username' = 'Siteowner', 'Password' = 'apitest1234' ),
    'cookies' = array()
    )
);

if ( is_wp_error( $response ) ) {
   $error_message = $response-get_error_message();
   return Something went wrong:  . $error_message;
} else {
   echo 'Response: pre';
   print_r( $response );
   echo '/pre';
   return;
}

Does anyone spot an obvious mistake in my syntax, or have a recommendation on where to troubleshoot? I see that wp_remote_post wraps the WP_Http class.

Update:

Confirmed that the $headers argument being sent to Requests::request looks like this:

Array
    (
        [0] = Content-Type: application/json
        [1] = Api-Key: {myapikey}
        [2] = Siteid: 99999
    )

Inspecting into the Requests::request method, it appears that the $transport (in this environment) is the following object:

Requests_Transport_cURL Object
(
    [headers] = 
    [response_data] = 
    [info] = 
    [version] = 468480
    [handle:protected] = Resource id #4
    [hooks:protected] = 
    [done_headers:protected] = 
    [stream_handle:protected] = 
    [response_bytes:protected] = 
    [response_byte_limit:protected] = 
)

And within it's request method, header array is still as above.

Update two:

This is interesting. In Requests_Transport_cURLs setup_handle method, when the CURLOPT_HTTPHEADER is set, $headers looks like this:

Array
(
    [0] = 0: Content-Type: application/json
    [1] = 1: Api-Key: a3f5be6229744000b9bc25f603e80c45
    [2] = 2: Siteid: -99
    [3] = Connection: close
)

On line 385:

385    curl_setopt($this-handle, CURLOPT_HTTPHEADER, $headers);

So perhaps I need to be sending a hash of key-value pairs as opposed to an array of json strings.

Topic wp-remote-post rest-api curl Wordpress

Category Web


As discovered above, headers need to be (seems so obvious now) key-value pairs, as opposed to an array of json-style key-values:

$headers = array();
$headers['Content-Type'] = 'application/json';
$headers['Api-Key'] = '{myapikey}';
$headers['Siteid'] = '99999';

And the body needs to be json so either:

'body' => "{\n    \"Username\": \"Siteowner\",\n    \"Password\": \"apitest1234\"\n}"

or

'body' => json_encode(array( 'Username' => 'Siteowner', 'Password' => 'apitest1234' ))

Good times, good times.

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.