Dropbox HTTP API - PHP cURL added header item boundary automatically - php

I'm new with the Dropbox API integrations, and I'm using the PHP cURL extension to make calls to the HTTP REST API, and when I try to make a request I receive the following string:
Error in call to API function "files/list_folder":
Bad HTTP "Content-Type" header:
"text/plain; boundary=----------------------------645eb1c4046b".
Expecting one of "application/json", "application/json; charset=utf-8",
"text/plain; charset=dropbox-cors-hack".
I'm sending this with code very similar to this:
$sUrl = "https://api.dropboxapi.com/2/files/list_folder";
$oCurl = curl_init($sUrl);
$aPostData = array('path' => '', 'recursive' => true, 'show_hidden' => true);
$sBearer = "MY_TOKEN";
$aRequestOptions = array(
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => array('Content-Type: text/plain',
'Authorization: Bearer ' . $sBearer),
CURLOPT_POSTFIELDS => $aPostData,
CURLOPT_RETURNTRANSFER => true);
curl_setopt_array($aRequestOptions);
$hExec = curl_exec($oCurl);
if ($hExec === false){
// Some error info in JSON format
} else {
var_dump($hExec);
}

As you have it, you're doing a multipart form upload, which isn't what the API expects.
There are a few things you need to do differently:
You should be sending up the parameters as JSON in the body.
You should set the Content-Type to application/json, accordingly.
There isn't a show_hidden parameter on /files/list_folder, but perhaps you meant to send include_deleted.
The curl_setopt_array method takes two parameters, the first of which should be the curl handle.
Here's an updated version of your code that works for me:
<?php
$sUrl = "https://api.dropboxapi.com/2/files/list_folder";
$oCurl = curl_init($sUrl);
$aPostData = array('path' => '', 'recursive' => true, 'include_deleted' => true);
$sBearer = "MY_TOKEN";
$aRequestOptions = array(
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => array('Content-Type: application/json',
'Authorization: Bearer ' . $sBearer),
CURLOPT_POSTFIELDS => json_encode($aPostData),
CURLOPT_RETURNTRANSFER => true);
curl_setopt_array($oCurl, $aRequestOptions);
$hExec = curl_exec($oCurl);
if ($hExec === false){
// Some error info in JSON format
} else {
var_dump($hExec);
}
?>

Related

PHP curl PUT does not continue respectively send payload/data

I need to PUT some json data to an API endpoint, which works as expected via command line curl, but not via php curl and I don't have any idea, why it doesn't.
my command is
curl -v --insecure --request PUT --url <https://blabla/blablabla> --user 'username:password' --header 'Content-Type: application/json' --data '<valid json data>'
but it doesn't work this way within php:
// get cURL resource
$curl = curl_init();
// set cURL options
$curloptions = array(
CURLOPT_PUT => true, // set method to PUT
CURLOPT_RETURNTRANSFER => true, // return the transfer as a string
CURLOPT_VERBOSE => true, // output verbose information
CURLOPT_SSL_VERIFYHOST => false, // ignore self signed certificates
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERNAME => $config['uag']['user'], // set username
CURLOPT_PASSWORD => $config['uag']['pass'], // set password
CURLOPT_HTTPHEADER => array( // set headers
"Content-Type: application/json",
),
CURLOPT_POSTFIELDS => $jsondata // set data to post / put
);
curl_setopt_array($curl, $curloptions);
foreach($serverurilist as $uri) {
// set url
curl_setopt($curl, CURLOPT_URL, $uri);
// send the request and save response to $response
$response = curl_exec($curl);
// stop if fails
if(!$response) {
die('Error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
}
var_dump($response);
}
// close curl resource to free up system resources
curl_close($curl);
What doesn't work? The payload / data doesn't get submitted. If I tcpdump the command line und php version without encryption, I can see, that the command line submits the data right after the Expect: 100-continue request and the HTTP/1.1 100 Continue response from the server. The php version doesn't do anything after the HTTP/1.1 100 Continue response and quits after reaching the timeout.
From documentation:
CURLOPT_PUT - true to HTTP PUT a file. The file to PUT must be set with CURLOPT_INFILE and CURLOPT_INFILESIZE.
and you are not using any file to provide content.
You should use CURLOPT_CUSTOMREQUEST => 'PUT'.
This is your same cUrl request exported from Postman:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://blabla/blablabla',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS =>'<valid json data>',
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ='
],
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
You should use this CURLOPT_CUSTOMREQUEST=>'PUT'

Convert Rest API call from PHP to RUBY

Im trying to convert a post connection to the walmart api, from php to ruby, this is the php version
$client_id = $data['client_id'];
$client_secret = $data['client_secret'];
$url = "https://marketplace.walmartapis.com/v3/token";
$uniqid = uniqid();
$authorization_key = base64_encode($client_id.":".$client_secret);
$code = "";
$ch = curl_init();
$options = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HEADER => false,
CURLOPT_POST =>1,
CURLOPT_POSTFIELDS => "grant_type=client_credentials",
CURLOPT_HTTPHEADER => array(
"WM_SVC.NAME: Walmart Marketplace",
"WM_QOS.CORRELATION_ID: $uniqid",
"Authorization: Basic $authorization_key",
"Accept: application/json",
"Content-Type: application/x-www-form-urlencoded",
),
);
curl_setopt_array($ch,$options);
$response = curl_exec($ch);
$code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
curl_close($ch);
and this is what i have so far:
url = "https://marketplace.walmartapis.com/v3/token/"
uniqid = "1234567890a1b"
uri = URI.parse(url)
request = Net::HTTP::Post.new(uri)
request["WM_SVC.NAME"] = "Walmart Marketplace"
request["WM_QOS.CORRELATION_ID"] = uniqid
request.basic_auth(client_id, client_secret)
request["Accept"] = "application/json"
request.content_type = "application/x-www-form-urlencoded"
request["WM_SVC.VERSION"] = "1.0.0"
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
http.request(request)
end
puts "error " + response.code
puts response.body
Now, im getting a 400 error, so something of the data im sending is incorrect or missing... comparing both, i dont have set the postfields option on ruby, for the POST request, not sure if the rest is required as well... any ideas?
Try adding this line:
request.body = 'grant_type=client_credentials'

SOAP data returns from Postman but not with Guzzle

Whenever I use Postman to make a soap post request, I get back the desired data. Using Guzzle, no data is returned. Im new to SOAP and using the resources online to go along.
I have omitted the variables for ease of read.
$xml = (
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:app="<ACTION-URL>">
<soapenv:Body>
<app:' . $functionName . '>
<request>'
. $requestBody .
'<authentication>
<username>'. $authObject->username .'</username>
<password>'. $authObject->password .'</password>
<user_id>'. $authObject->userId .'</user_id>
<dealer_id>'. $authObject->clientBranchId .'</dealer_id>
</authentication>
</request>
</app:' . $functionName . '>
</soapenv:Body>
</soapenv:Envelope>'
);
private function makeSOAPRequest($xml)
{
$client = new \GuzzleHttp\Client();
$options = [
'headers' => [
'Content-Type' => 'text/xml; charset=utf-8'
],
'body' => $xml,
'Authenticate' => [env('USERNAME'), env('PASSWORD')]
];
$url = env('ROSETTA_API');
$promise = $client->requestAsync('POST', $url, $options);
$response = $promise->wait();
$xml = simplexml_load_string($response->getBody(),'SimpleXMLElement',LIBXML_NOCDATA);
if ($xml) {
$json = json_encode($xml);
return json_decode($json, true);
}
return false;
}
Calling makeSOAPRequest(..), I get back false. Using the same xml data in Postman, data is returned. Is there anything I've missed in the request header?
Edit to use cURL
// Copied from Postman:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://<URL>",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $xml,
CURLOPT_HTTPHEADER => array(
"Cookie: PHPSESSID=6419f1d96025a4a2c4d454de33fc6820"
),
));
$response = curl_exec($curl);
curl_close($curl);
return $response; // xml data in string format.
cUrl does work but not Guzzle. How to return as json? When I use simplexml_load_string, it's empty.
Try to use below parameters in your curl:
CURLOPT_SSL_VERIFYPEER => 1
CURLOPT_POST => true
// IF NEEDED
CURLOPT_HTTPAUTH => CURLAUTH_ANY
// IF NEEDED
CURLOPT_USERPWD => $soapUser.":".$soapPassword)
For Checking Error After curl_exec and before curl_close
if( curl_errno($ch) ){
print_r(curl_error($curl));
}
In add these headers in your header if needed:
"accept" => "*/*",
// IF NEEDED
"accept-encoding" => "gzip, deflate"
Add your request code in try catch block:
try{
//request code
}
catch(Exception $e){
print_r($e->getCode());
print_r($e->getMessage());
}

Missing parameters when requesting OAUTH token survey monkey v3

I'm trying to obtain my "long lived access token" using CURL/PHP but I'm receiving the error "Missing parameters for client_id, client_secret, code, grant_type, redirect_uri".
The URL I'm calling is where you can clearly see the parameters I'm trying to pass in!
https://api.surveymonkey.net/oauth/token?client_secret='.urlencode($client_secret).'&code='.urlencode($short_token).'&redirect_uri='.urlencode($redirect_url).'&client_id='.urlencode($client_id).'&grant_type=authorization_code
I'm also using the content-type of "application/x-www-form-urlencoded" as per the docs (see below).
My CURL request:
function survey_monkey_curl_request($url, $params=[], $request_type = 'get', $access_token) {
print_r($url);
$ch = curl_init();
$headers = [
"Content-Type: application/x-www-form-urlencoded",
"Authorization: bearer " .$access_token
];
$opts = [
CURLOPT_URL => $url,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_0,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => 0,
];
if ($request_type == 'post') {
$opts[CURLOPT_POST] = 1;
//$opts[CURLOPT_POSTFIELDS] = json_encode($params);
}
if ($request_type == 'patch') {
$opts[CURLOPT_CUSTOMREQUEST] = "PATCH";
$opts[CURLOPT_POSTFIELDS] = json_encode($params);
}
curl_setopt_array($ch, $opts);
$result = curl_exec($ch);
if ($result === false) {
curl_close($ch);
throw new Exception(curl_error($ch));
}
curl_close($ch);
return $result;
}
Where am I going wrong?
Straight from the documentation it looks like to get the long-lived token you need to post your fields:
//Exchange for long-lived token
curl -i -X POST https://api.surveymonkey.net/oauth/token -d \
"client_secret=YOUR_CLIENT_SECRET \
&code=AUTH_CODE \
&redirect_uri=YOUR_REDIRECT_URI \
&client_id=YOUR_CLIENT_ID \
&grant_type=authorization_code"
https://developer.surveymonkey.com/api/v3/?shell#new-authentication
When you append your parameters onto your url you are sending then as GET request paramters
You need to put your data string into CURL POSTFIELDS and do not json encode
The PHP Answer
<?php
$ch = curl_init();
$data = [
'client_secret' => $YOUR_CLIENT_SECRET,
'code' => $AUTH_CODE,
'redirect_url' => $YOUR_REDIRECT_URI,
'client_id' => $YOUR_CLIENT_ID,
'grant_type' => 'authorization_code'
];//set your data as an array
$headers = [
"Content-Type: application/x-www-form-urlencoded",
"Authorization: bearer " . $access_token
];
$opts = [
CURLOPT_URL => $url,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_0,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => 0,
];
if ($request_type == 'post') {
$opts[CURLOPT_POST] = 1;
$opts[CURLOPT_POSTFIELDS] = http_build_query($data);// this will build your data string from the array
}
curl_setopt_array($ch, $opts);
$result = curl_exec($ch);
curl_close($ch);
return $result;

How to post a status update to Sina Weibo via OAuth2?

I'm trying to post a status update to the Chinese microblogging website Sina Weibo, via PHP/cURL and OAuth2.
I'm running into this error:
{"error":"auth
faild!","error_code":21301,"request":"/2/statuses/update.json"}
My PHP:
<?php
$ch = curl_init('https://api.weibo.com/2/statuses/update.json');
$headers = array(
'Authorization: Bearer '.$access_token,
'Content-Type: application/x-www-form-urlencoded');
$postData = array('access_token' => '2.00x123456789', 'status' => 'hello');
curl_setopt_array($ch, array(
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_SSL_VERIFYHOST => TRUE,
CURLOPT_POST => TRUE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $postData
));
$response = curl_exec($ch);
echo $response;
curl_close($ch);
?>
I authorized the app with the OAuth2 scope all and the token is valid.
What could be the reason for the error?
Remove your http header
'Content-Type: application/x-www-form-urlencoded'
Replace post fields with:
CURLOPT_POSTFIELDS => http_build_query($postData)
And now Be Happy!

Categories