POST call doesn't work correctly? - php

I need to do a POST call to save data on a server. The server requires for some items a JSON-Encoded List. However when I do the post call and I look at $result, the data of the "JSON-Encoded List" is not saved and the items are null. The POST call is however successful.
$items = json_encode((array(
"name" => $_GET['title'],
"sub_type" => $subtype_fd,
"calories" => intval($_GET['calories']),
"carbohydrate" => floatval($_GET['carbohydrate']),
"cholesterol" => floatval($_GET['cholesterol']),
"fiber" => floatval($_GET['fiber']),
"protein" => floatval($_GET['protein']),
"saturated_fat" => floatval($_GET['saturated_fat']),
"unsaturated_fat" => floatval($_GET['unsaturated_fat']),
"sodium" => floatval($_GET['sodium']),
"sugar" => floatval($_GET['sugar'])
)));
var_dump($items);
$data = array('note' => $_GET['title'], 'sub_type' => $subtype_bld, 'items' => $items);
$options = array(
'http' => array(
"header" => "Content-Type: application/x-www-form-urlencoded\r\nAuthorization: Bearer {$_COOKIE['access_token']}\r\n",
'method' => 'POST',
'content' => $data
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
The Info from API
Host: jawbone.com
Accept: application/json
Content-Type: multipart/form-data

The content context option should be a string, you're providing an array. It's supposed to be a string in URL-encoded format. The http_build_str function will convert an associative array into this format. So use:
'content' => http_build_str($data)

Related

Using an array as request headers in PHP

I'm trying to send a GET request to an API using PHP stream_context_create and file_get_contents.
I need to add API keys to the headers of my request, I'm storing these in an array so I easily edit them later and use them in multiple functions. What is a good way to include these arrays as headers?
In this case the key of the array would be the header keys and the value of the array the value of the header.
Some code to explain the problem
<?php
$api = array(
"X-Api-Id" => "id",
"X-Api-Key" => "key",
"X-Api-Secret" => "secret"
);
$options = array(
"http" => array(
"header" => "Content-type: application/x-www-form-urlencoded\r\n", // here I need to add the $api array
"method" => "GET"
)
);
return file_get_contents("example.com", FALSE, stream_context_create($options));
?>
Simply add the info to the header.
<?php
$api = [
'X-Api-Id' => 'id',
'X-Api-Key' => 'key',
'X-Api-Secret' => 'secret',
];
$headerData['Content-type'] = 'application/x-www-form-urlencoded';
$headerData = array_merge($headerData, $api);
array_walk($headerData, static function(&$v, $k) { $v = $k.': '.$v; });
$options = array(
'http' => [
'header' => implode("\n", $headerData),
'method' => 'GET'
]
);
return file_get_contents('example.com', FALSE, stream_context_create($options));
?>
To encode the data you can use http_build_query().
To add it to the header options you should be able to do something like:
$options = array(
"http" =>array(
'method' => 'POST', // GET in your case(?)
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => http_build_query($api)
)
);

Dropbox API - Error: expected list got dict

I am currently building a routine that needs to download files from one specific Dropbox folder , send them to another server and then move them to another folder on Dropbox.
I am using the /files/move_batch API endpoint for Dropbox to do so.
Here are the params sent to the API to move multiples files (well I'm only trying to move one file right now as it's still not working) :
$params = array(
'headers' => array(
'method' => 'POST',
'content-type' => 'application/json; charset=utf-8',
),
'body' => json_encode(array(
'entries' => array(
'from_path' => self::$files[0],
'to_path' => '/Applications/Archives/' . substr(self::$files[0], strrpos(self::$files[0], '/') + 1),
),
'autorename' => true,
)),
);
But I keep getting the same error message :
Error in call to API function "files/move_batch": request body: entries: expected list, got dict
I don't know what the API means by a list or how it should be formated.
The entries value should be a list of dict, one per file you want to move, each one containing both a from_path and a to_path. Your code is supplying the entries value to be a single dict though. (In PHP you can make both lists and dicts using the array keyword.)
It's easier to see and work with when you break it into pieces. Here's a working sample that does that.
<?php
$fileop1 = array(
'from_path' => "/test_39995261/a/1.txt",
'to_path' => "/test_39995261/b/1.txt"
);
$fileop2 = array(
'from_path' => "/test_39995261/a/2.txt",
'to_path' => "/test_39995261/b/2.txt"
);
$parameters = array(
'entries' => array($fileop1, $fileop2),
'autorename' => true,
);
$headers = array('Authorization: Bearer <ACCESS_TOKEN>',
'Content-Type: application/json');
$curlOptions = array(
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($parameters),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_VERBOSE => true
);
$ch = curl_init('https://api.dropboxapi.com/2/files/move_batch');
curl_setopt_array($ch, $curlOptions);
$response = curl_exec($ch);
echo $response;
curl_close($ch);
?>
To move just one file using this batch endpoint, you would change that line to something like:
'entries' => array($fileop1),

Update video using youtube api

I want to update a video using google api v3 and i get the error 400 Bad Request.
This is my code.
$url = 'https://www.googleapis.com/youtube/v3/videos?part=snippet&videoId='.$_GET['videoId'].'&access_token='.Session::get('access_token');
$params = array(
"id"=> $_GET['videoId'],
"kind"=> "youtube#video",
'snippet' => array(
"title"=> "I'm being changed.",
"categoryId"=> "10",
"tags"=> array(
"humanities",
"Harpham",
"BYU"
),
'description' => 'test!'
)
);
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'PUT',
'content' => http_build_query($params),
),
);
$context = stream_context_create($options);
$result = json_decode(file_get_contents($url, false, $context));
I think since you don't set all parameters inside snippet, that's giving an error. What you can do is, first getting that video with videos->list, then updating the field you are interested in and sending back the update request with the whole object back.
Here's an example also utilizing php client library: https://github.com/youtube/api-samples/blob/master/php/update_video.php

How to construct an AJAX JSON string with PHP to send with POST

I have a simple xmlhttprequest with AJAX and want to rebuild this with PHP.
var data = {};
var payload = {
"flags" : true,
"codes" : true,
"units" : true
};
data.payload = JSON.stringify(payload);
$.ajax({
type : 'POST',
url : 'http://httpbin.org/post',
data : data,
success : function(response) {
var arr = JSON.stringify(response);
document.getElementById('placeholder').innerHTML = arr;
}
});
This works fine!
Now my Version with PHP:
$data = array(
'payload' => array(
'flags' => true,
'codes' => true,
'units' => true
)
);
$options = array(
"http" => array(
"method" => "POST",
"header" => "Content-Type: application/json\r\n",
"content" => json_encode($data)
)
);
$url = "http://httpbin.org/post";
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
var_dump($response);
When I compare the results there is a difference in the structure.
Ajax looks like this:
{"form":{"payload":"{\"flags\":\"true\",
and PHP looks like this:
{"form": {},..."data": "{\"payload\":{\"flags\":\"true\",
Why is in PHP the "form" empty?
I've tried it an extra Array "form", but when I look at the result there is a second "form" in the string.
You use improper way of building POST data.
Try this:
$payload = array(
'flags' => true,
'codes' => true,
'units' => true
);
$data = array(
'payload' => json_encode($payload)
);
$options = array(
"http" => array(
"method" => "POST",
"header" => "Content-Type: application/x-www-form-urlencoded\r\n",
"content" => http_build_query($data)
)
);
Explanation
In your JS code POST data is an object containing one key-value pair {"payload": json} where json is json-encoded string representing payload object. This POST data object finally results (in $.ajax implementation) in a url-encoded string which look like this: payload=%7B%22flags%22%3Atrue%2C%22codes%22%3Atrue%2C%22units%22%3Atrue%7D.
Described process is exactly reproduced by my php code.
Have you tried to trigger json_last_error() right after encoding your array ?
$options = array(
"http" => array(
"method" => "POST",
"header" => "Content-Type: application/json\r\n",
"content" => json_encode($data)
)
);
$error = json_last_error();
echo $error;
In case of a silent json error, maybe it could give you a clue.
Let us know :)

Empty POST data in first query

I have a strange problem with PHP script and sending data by POST.
Script source where I receive POST data:
<?php
print_r($GLOBALS);
?>
Script where I send POST data:
<?php
$url = 'http://server.com/script.php';
$data = array(
"request" => '
{
"variable": "some data"
}'
);
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
echo $result = file_get_contents($url, false, $context);
?>
When I call this script first time it return:
Array ( [GLOBALS] => Array *RECURSION* [_POST] => Array ( ) [_GET] => Array ( ) [_COOKIE] => Array ( ) [_FILES] => Array ( ) )
When I repeat query it's OK - Array show POST data. After a few minutes it is again empty.
I tried set different settings in .htaccess file, but it does not help.
PS. Same script on other server works great.
Do you have any ideas?

Categories