I am trying to use guzzle to do a post request to an open API. I am also sending the post data as follows. For some reason i am getting a 400 bad request
$req = $client->request('POST',$this->base_url.'nutrients?app_id='.$this->app_id.'&app_key='.$this->api_key,[
'headers' => [
'Content-Type' => 'application/json'
],
\GuzzleHttp\RequestOptions::JSON => [
"yield" => $portions,
"ingredients" => [
"quantity" => $portions,
"measureURI" => "\"$f_uri\"",
"foodURI" => "\"$m_uri\""
]
]
]);
$response = $client->send($req);
$decoded = json_decode($response->getBody());
dd($decoded);
The api documentation shows the method in curl as follows:
curl call:
curl -d #food.json -H "Content-Type: application/json" "https://api.edamam.com/api/food-database/nutrients?app_id=${YOUR_APP_ID}&app_key=${YOUR_APP_KEY}"
food.json:
{
"yield": 1,
"ingredients": [
{
"quantity": 1,
"measureURI": "http://www.edamam.com/ontologies/edamam.owl#Measure_unit",
"foodURI": "http://www.edamam.com/ontologies/edamam.owl#Food_11529"
}
]
}
My links for measureURI and foodURI are generated correctly.
You don't need to do ->send() after the ->request(), it already returns an instance of ResponseInterface.
So just
$response = $client->request('POST', $this->base_url.'nutrients?app_id='.$this->app_id.'&app_key='.$this->api_key, [
// ...
]
]);
$decoded = json_decode($response->getBody()->getContents());
Related
I have this cURL command that I need to convert to PHP using Guzzle 7. I've have been researching this for a few (well, more than a few) days and getting nowhere fast. The cURL command uses the Simpli.fi api to create an organization under the parent org.
curl -i -X POST -H "X-App-Key: xxxx-xx-xx-xx-xxxxxx" -H "X-User-Key: xxxx-xx-xx-xx-xxxxxx" \
-H "Content-Type: application/json" \
-d '{
"organization": {
"name": "My New Organization",
"parent_id": "5786",
"custom_id": "<Put your organization identifier here or omit this optional field>"
}
}' \
"https://app.simpli.fi/api/organizations"
I was able to convert it using this website but it doesn't use Guzzle: https://onlinedevtools.in/curl
Here's what it gave me:
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$headers = array(
'X-App-Key' => 'xxxx-xx-xx-xx-xxxxxx',
'X-User-Key' => 'xxxx-xx-xx-xx-xxxxxx',
'Content-Type' => 'application/json'
);
$data = '{\n "organization": {\n "name": "My New Organization",\n "parent_id": "5786",\n "custom_id": "<Put your organization identifier here or omit this optional field>"\n }\n }';
$response = Requests::post('https://app.simpli.fi/api/organizations', $headers, $data);
Here's what I've tried so far aside from the converted code above:
public static function createOrganization()
{
self::init();
$client = new Client(['debug' => true]);
$request = $client->request('POST',
self::$baseUrl.'/organizations', [
'multipart' => [
[
'name' => 'data',
'contents' => "{'organization':{'name':'Pete's Pet Pagoda','parent_id':'1052385'}}",
],
],
'headers' => [
'x-app-key' => self::$appKey,
'x-user-key' => self::$userKey,
'Content-Type' => 'application/json',
]
]);
dd($response = $request->getStatusCode());
}
I'm getting quite a few different errors however this is the latest:
curl_setopt_array(): cannot represent a stream of type Output as a STDIO FILE*
Can anyone tell me what I'm doing wrong? Is there something missing?
UPDATE: After further research into this issue and chatting with a developer on the Laracast Slack channel, I've come to learn that this is a bug with the ['debug' => true] option when running on a Windows system and is described on this GITHUB page: https://github.com/guzzle/guzzle/issues/1413
I'm running on a Windows 10 Pro system. I corrected it on my end by changing the debug option to use fopen() like this:
'debug' => fopen('php://stderr', 'w'),
I use PHPStorm. It suggested using the 'wb' to make it binary safe. After changing it, the post requests worked fine.
You need to use body, not multipart. You can also use json.
$request = $client->request('POST',
self::$baseUrl.'/organizations', [
'headers' => [
'x-app-key' => self::$appKey,
'x-user-key' => self::$userKey,
'Content-Type' => 'application/json',
],
'body' => [
'{"organization":
[
{
"name":"Pete`s Pet Pagoda",
"parent_id":"1052385"
}
]
}',
],
]);
method 2
You can pass array to the json request option and it will convert it to json when sending the guzzle request. No need to use header as application/json as it applies internally.
$client->request('POST',
self::$baseUrl.'/organizations', [
'headers' => [
'x-app-key' => self::$appKey,
'x-user-key' => self::$userKey,
'Content-Type' => 'application/json',
],
'json' => [
"organization" => [
[
"name" => "Pete`s Pet Pagoda"
"parent_id" => "1052385"
]
]
],
]);
I hope this will help you. For further debugging use Middleware::tap(find more help here middleware+json+request)
try{
$client = new Client();
$response = $client->request('POST', self::$baseUrl.'/organizations',
[
'headers' => [
'x-app-key' => self::$appKey,
'x-user-key' => self::$userKey,
'Content-Type' => 'application/json',
],
'json' => [
'organization' =>
[
"name" => "some_name_value",
"parent_id" => "id_here",
"custom_id" => "custom id here"
]
]
]);
$_response = json_decode($response->getBody()->getContents(), true);
}
catch(BadResponseException $e){
$response = $e->getResponse();
$errorArray = json_decode($response->getBody()->getContents(), true);
//echo "<pre>";
//print_r($errorArray);
//return some message from errorarray;
}
I've got this CURL that I'm executing on the command line and it successfully creates content in my CMS (Drupal 9).
curl \
--user username:9aqW72MUbFQR4EYh \
--header 'Accept: application/vnd.api+json' \
--header 'Content-type: application/vnd.api+json' \
--request POST http://www.domain.drupal/jsonapi/node/article \
--data-binary #payload.json
and the JSON file as:
{
"data": {
"type": "node--article",
"attributes": {
"title": "My custom title",
"body": {
"value": "Custom value",
"format": "plain_text"
}
}
}
}
Working like a charm and data is being created.
I've been trying to do this in GuzzleHttp but couldn't get it working.
Get is working:
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
$url = 'http://www.domain.drupal';
$content_client = new GuzzleHttp\Client([
'base_uri' => $url,
'timeout' => 20.0,
]);
$res = $content_client->request('GET', '/jsonapi/node/article/71adf560-044c-49e0-9461-af593bad0746');
For POST, I've got probably around 10 versions trial and error but nothing worked.
How can I POST my JSON/Content to Drupal or how can I correctly implement the CURL in Guzzle?
If you want a simple post request to send json body with your headers you can do it simply without using Psr7 Request. Guzzle utilizes PSR-7 as the HTTP message interface.
use GuzzleHttp\Client;
$url = 'http://www.domain.drupal';
$content_client = new Client([
'base_uri' => $url,
'timeout' => 20.0,
]);
$headers = [
'Content-type' => 'application/vnd.api+json',
'Accept' => 'application/vnd.api+json'
];
$payload['data'] = [
'type' => 'node--article',
'attributes' => [
"title" => "My custom title",
"body" => [
"value" => "Custom value",
"format" => "plain_text"
]
]
];
$guzzleResponse = $content_client->post('/jsonapi/node/article/71adf560-044c-49e0-9461-af593bad0746', [
'json' => json_encode($payload),
'headers' => $headers
]);
if ($guzzleResponse->getStatusCode() == 200) {
$response = json_decode($guzzleResponse->getBody());
}
You can write it in try catch block with using RequestException (see this Catching exceptions from Guzzle to know more about it.)
I haven't tried using cUrl Request with API and converting it to Guzzle HTTP.
I need to convert this cUrl to a working guzzle http post request to try the API
curl -X POST
"https://urltosendblahblah" -H "Content-Type: application/json" -d
{
"outboundRewardRequest" : {
"app_id" : "B54z9Ug55zLh5rTGRT5g6hq64pGUq6ap",
"app_secret" : "f6554137d08f5607a696cd40741993758c411af3bb5f6c230270ec26e8d54126",
"rewards_token" : "I7SkxKYid_F_p-JSgTejow",
"address" : "9271051129",
"promo" : "LOAD 50"
}
}
Currently I had done this with my Guzzle Http but receiving 500 response
public function loadSample(){
$url = "";
$request = $this->client->post($url, [
'verify'=>false,
'outboundRewardRequest' => [
'app_id'=>'',
'app_secret'=> '',
'rewards_token'=>'==',
'address'=>'',
'promo'=>''
]
]);
$response = $request->getBody();
dd($response);
}
thank you!
$request = $this->client->post($url, [
'headers' => [
'verify' => false
],
'form_params' => ['outboundRewardRequest' => [
'app_id'=>'',
'app_secret'=> '',
'rewards_token'=>'==',
'address'=>'',
'promo'=>''
]],
'debug' => false,
]);
Try this approach when using guzzle. Your body parameters must be a part of the form_params array.
Also you can set your guzzle debugging to false so you don't have any issues there.
The expected key for the request body is body source. So try changing outboundRewardRequest to body.
Put your data in the json attribute or form_params depending on how it is received.
public function loadSample(){
$url = "";
$request = $this->client->post($url, [
'verify'=>false,
'json' => [
'outboundRewardRequest' => [
'app_id'=>'',
'app_secret'=> '',
'rewards_token'=>'==',
'address'=>'',
'promo'=>''
]
]
]);
$response = $request->getBody();
dd($response);
}
I'm trying to create subscriptions with microsoft graph in php, however I am unable to see what is going wrong at this point.
The code is breaking at the following:
protected $http_subscribe = "https://graph.microsoft.com/v1.0/subscriptions";
public function getSubscriptions()
{
if(empty($this->token)) {
dd('no token supplied'); //some debugging
}
$date = $this->endTimeDate->format('Y-m-d'); //This is Carbon date
$time = $this->endTimeDate->format('H:i:s.u');
$response = $this->client->request('POST', $this->http_subscribe, [
'headers' => [
'Authorization' => 'Bearer ' . $this->token,
'Content-Type' => "application/json"
], 'form_params' => [
"changeType" => "created,updated",
"notificationUrl" => "https://website.test/notify",
"resource" => "me/mailFolders('Inbox')/messages",
"expirationDateTime" => $date.'T'.$time,
"clientState" => "secretClientValue"
]
]);
dd($response);
}
The full error I'm getting is:
"""
{\r\n
"error": {\r\n
"code": "BadRequest",\r\n
"message": "Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format.",\r\n
"innerError": {\r\n
"request-id": "063d9947-80fd-461d-a70e-q0bd8eee9d56",\r\n
"date": "2018-08-07T08:20:54"\r\n
}\r\n
}\r\n
}
"""
Now I get what the error says, my json would be invalid, however this array is in correct json format, I'm using Guzzle as my Client.
You should use json option. Try this:
$response = $this->client->request('POST', $this->http_subscribe, [
'headers' => [
'Authorization' => 'Bearer ' . $this->token,
],
'json' => [
"changeType" => "created,updated",
"notificationUrl" => "https://website.test/notify",
"resource" => "me/mailFolders('Inbox')/messages",
"expirationDateTime" => $date.'T'.$time,
"clientState" => "secretClientValue",
],
]);
This should be soo simple but I have spent hours searching for the answer and am truly stuck. I am building a basic Laravel application and am using Guzzle to replace the CURL request I am making at the moment. All the CURL functions utilise raw JSON variables in the body.
I am trying to create a working Guzzle client but the server is respsonding with 'invalid request' and I am just wondering if something fishy is going on with the JSON I am posting. I am starting to wonder if you can not use raw JSON in the Guzzle POST request body? I know the headers are working as I am receiving a valid response from the server and I know the JSON is valid as it is currently working in a CURL request. So I am stuck :-(
Any help would be sooo greatly appreciated.
$headers = array(
'NETOAPI_KEY' => env('NETO_API_KEY'),
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'NETOAPI_ACTION' => 'GetOrder'
);
// JSON Data for API post
$GetOrder = '{
"Filter": {
"OrderID": "N10139",
"OutputSelector": [
"OrderStatus"
]
}
}';
$client = new client();
$res = $client->post(env('NETO_API_URL'), [ 'headers' => $headers ], [ 'body' => $GetOrder ]);
return $res->getBody();
You can send a regular array as JSON via the 'json' request option; this will also automatically set the right headers:
$headers = [
'NETOAPI_KEY' => env('NETO_API_KEY'),
'Accept' => 'application/json',
'NETOAPI_ACTION' => 'GetOrder'
];
$GetOrder = [
'Filter' => [
'OrderID' => 'N10139',
'OutputSelector' => ['OrderStatus'],
],
];
$client = new client();
$res = $client->post(env('NETO_API_URL'), [
'headers' => $headers,
'json' => $GetOrder,
]);
Note that Guzzle applies json_encode() without any options behind the scenes; if you need any customisation, you're advised to do some of the work yourself
$res = $client->post(env('NETO_API_URL'), [
'headers' => $headers + ['Content-Type' => 'application/json'],
'body' => json_encode($getOrders, ...),
]);
Guzzle 7 Here
The below worked for me with raw json input
$data = array(
'customer' => '89090',
'username' => 'app',
'password' => 'pwd'
);
$url = "http://someendpoint/API/Login";
$client = new \GuzzleHttp\Client();
$response = $client->post($url, [
'headers' => ['Content-Type' => 'application/json', 'Accept' => 'application/json'],
'body' => json_encode($data)
]);
print_r(json_decode($response->getBody(), true));
For some reasons until I used the json_decode on the response, the output wasn't formatted.
You probably need to set the body mime type. This can be done easily using the setBody() method.
$request = $client->post(env('NETO_API_URL'), ['headers' => $headers]);
$request->setBody($GetOrder, 'application/json');