Related
Does anybody know the correct way to post JSON using Guzzle?
$request = $this->client->post(self::URL_REGISTER,array(
'content-type' => 'application/json'
),array(json_encode($_POST)));
I get an internal server error response from the server. It works using Chrome Postman.
For Guzzle 5, 6 and 7 you do it like this:
use GuzzleHttp\Client;
$client = new Client();
$response = $client->post('url', [
GuzzleHttp\RequestOptions::JSON => ['foo' => 'bar'] // or 'json' => [...]
]);
Docs
The simple and basic way (guzzle6):
$client = new Client([
'headers' => [ 'Content-Type' => 'application/json' ]
]);
$response = $client->post('http://api.com/CheckItOutNow',
['body' => json_encode(
[
'hello' => 'World'
]
)]
);
To get the response status code and the content of the body I did this:
echo '<pre>' . var_export($response->getStatusCode(), true) . '</pre>';
echo '<pre>' . var_export($response->getBody()->getContents(), true) . '</pre>';
For Guzzle <= 4:
It's a raw post request so putting the JSON in the body solved the problem
$request = $this->client->post(
$url,
[
'content-type' => 'application/json'
],
);
$request->setBody($data); #set body!
$response = $request->send();
This worked for me (using Guzzle 6)
$client = new Client();
$result = $client->post('http://api.example.com', [
'json' => [
'value_1' => 'number1',
'Value_group' =>
array("value_2" => "number2",
"value_3" => "number3")
]
]);
echo($result->getBody()->getContents());
$client = new \GuzzleHttp\Client();
$body['grant_type'] = "client_credentials";
$body['client_id'] = $this->client_id;
$body['client_secret'] = $this->client_secret;
$res = $client->post($url, [ 'body' => json_encode($body) ]);
$code = $res->getStatusCode();
$result = $res->json();
You can either using hardcoded json attribute as key, or you can conveniently using GuzzleHttp\RequestOptions::JSON constant.
Here is the example of using hardcoded json string.
use GuzzleHttp\Client;
$client = new Client();
$response = $client->post('url', [
'json' => ['foo' => 'bar']
]);
See Docs.
$client = new \GuzzleHttp\Client(['base_uri' => 'http://example.com/api']);
$response = $client->post('/save', [
'json' => [
'name' => 'John Doe'
]
]);
return $response->getBody();
This works for me with Guzzle 6.2 :
$gClient = new \GuzzleHttp\Client(['base_uri' => 'www.foo.bar']);
$res = $gClient->post('ws/endpoint',
array(
'headers'=>array('Content-Type'=>'application/json'),
'json'=>array('someData'=>'xxxxx','moreData'=>'zzzzzzz')
)
);
According to the documentation guzzle do the json_encode
Solution for $client->request('POST',...
For those who are using $client->request this is how you create a JSON request:
$client = new Client();
$res = $client->request('POST', "https://some-url.com/api", [
'json' => [
'paramaterName' => "parameterValue",
'paramaterName2' => "parameterValue2",
]
'headers' => [
'Content-Type' => 'application/json',
]
]);
Guzzle JSON Request Reference
Php Version: 5.6
Symfony version: 2.3
Guzzle: 5.0
I had an experience recently about sending json with Guzzle. I use Symfony 2.3 so my guzzle version can be a little older.
I will also show how to use debug mode and you can see the request before sending it,
When i made the request as shown below got the successfull response;
use GuzzleHttp\Client;
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
"Content-Type" => "application/json"
];
$body = json_encode($requestBody);
$client = new Client();
$client->setDefaultOption('headers', $headers);
$client->setDefaultOption('verify', false);
$client->setDefaultOption('debug', true);
$response = $client->post($endPoint, array('body'=> $body));
dump($response->getBody()->getContents());
#user3379466 is correct, but here I rewrite in full:
-package that you need:
"require": {
"php" : ">=5.3.9",
"guzzlehttp/guzzle": "^3.8"
},
-php code (Digest is a type so pick different type if you need to, i have to include api server for authentication in this paragraph, some does not need to authenticate. If you use json you will need to replace any text 'xml' with 'json' and the data below should be a json string too):
$client = new Client('https://api.yourbaseapiserver.com/incidents.xml', array('version' => 'v1.3', 'request.options' => array('headers' => array('Accept' => 'application/vnd.yourbaseapiserver.v1.1+xml', 'Content-Type' => 'text/xml'), 'auth' => array('username#gmail.com', 'password', 'Digest'),)));
$url = "https://api.yourbaseapiserver.com/incidents.xml";
$data = '<incident>
<name>Incident Title2a</name>
<priority>Medium</priority>
<requester><email>dsss#mail.ca</email></requester>
<description>description2a</description>
</incident>';
$request = $client->post($url, array('content-type' => 'application/xml',));
$request->setBody($data); #set body! this is body of request object and not a body field in the header section so don't be confused.
$response = $request->send(); #you must do send() method!
echo $response->getBody(); #you should see the response body from the server on success
die;
--- Solution for * Guzzle 6 * ---
-package that you need:
"require": {
"php" : ">=5.5.0",
"guzzlehttp/guzzle": "~6.0"
},
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'https://api.compay.com/',
// You can set any number of default request options.
'timeout' => 3.0,
'auth' => array('you#gmail.ca', 'dsfddfdfpassword', 'Digest'),
'headers' => array('Accept' => 'application/vnd.comay.v1.1+xml',
'Content-Type' => 'text/xml'),
]);
$url = "https://api.compay.com/cases.xml";
$data string variable is defined same as above.
// Provide the body as a string.
$r = $client->request('POST', $url, [
'body' => $data
]);
echo $r->getBody();
die;
Simply use this it will work
$auth = base64_encode('user:'.config('mailchimp.api_key'));
//API URL
$urll = "https://".config('mailchimp.data_center').".api.mailchimp.com/3.0/batches";
//API authentication Header
$headers = array(
'Accept' => 'application/json',
'Authorization' => 'Basic '.$auth
);
$client = new Client();
$req_Memeber = new Request('POST', $urll, $headers, $userlist);
// promise
$promise = $client->sendAsync($req_Memeber)->then(function ($res){
echo "Synched";
});
$promise->wait();
I use the following code that works very reliably.
The JSON data is passed in the parameter $request, and the specific request type passed in the variable $searchType.
The code includes a trap to detect and report an unsuccessful or invalid call which will then return false.
If the call is sucessful then json_decode ($result->getBody(), $return=true) returns an array of the results.
public function callAPI($request, $searchType) {
$guzzleClient = new GuzzleHttp\Client(["base_uri" => "https://example.com"]);
try {
$result = $guzzleClient->post( $searchType, ["json" => $request]);
} catch (Exception $e) {
$error = $e->getMessage();
$error .= '<pre>'.print_r($request, $return=true).'</pre>';
$error .= 'No returnable data';
Event::logError(__LINE__, __FILE__, $error);
return false;
}
return json_decode($result->getBody(), $return=true);
}
The answer from #user3379466 can be made to work by setting $data as follows:
$data = "{'some_key' : 'some_value'}";
What our project needed was to insert a variable into an array inside the json string, which I did as follows (in case this helps anyone):
$data = "{\"collection\" : [$existing_variable]}";
So with $existing_variable being, say, 90210, you get:
echo $data;
//{"collection" : [90210]}
Also worth noting is that you might want to also set the 'Accept' => 'application/json' as well in case the endpoint you're hitting cares about that kind of thing.
Above answers did not worked for me somehow. But this works fine for me.
$client = new Client('' . $appUrl['scheme'] . '://' . $appUrl['host'] . '' . $appUrl['path']);
$request = $client->post($base_url, array('content-type' => 'application/json'), json_encode($appUrl['query']));
use GuzzleHttp\Client;
function insert_freshdesk_note($ticketId, $content, $attachments=null)
{
if(is_null($content)) {
return false;
}
$url = 'https://mydomain.freshdesk.com/api/v2/tickets/'.$ticketId.'/notes';
$method = 'POST';
$userName = config('freshdesk_api_key');
$password = 'password';
$data = (!empty($attachments)) ? [
"attachments[]" => $attachments,
"body" => $content,
"private" => false,
] : [
"body" => $content,
"private" => false,
];
$options = (!empty($attachments)) ? [
'json' => $data,
'auth' => [$userName, $password],
'headers' => ['content-type' => 'multipart/form-data']
] : [
'json' => $data,
'auth' => [$userName, $password]
];
$client = new Client();
try {
$response = $client->request($method, $url, $options);
return json_decode($response->getBody(), true);
} catch (Exception $e) {
Log::error($e);
}
}
Above code is working fine without attachments but when an attachment comes into the picture it's throwing the following error:-
GuzzleHttp\Exception\ClientException: Client error: `POST https://mydomain.freshdesk.com/api/v2/tickets/13033/notes` resulted in a `400 Bad Request` response:
{"description":"Validation failed","errors":[{"field":"{\"attachments","message":"Unexpected/invalid field in request","
I am working according to the documentation and I have hit a dead end as of this point. I tried other permutations and combinations but via those, I wasn't able to resolve this problem.
Can anyone please help me.
Here is the link of the documentation of freshdesk
And in $attachments[] = '#/path/to/xyz.ext' this particular is going.
The function call will go like this:-
insert_freshdesk_note($this->freshdesk_ticket_id, $noteText, $image->image_full_path);
In the above question, I was trying to achieve the addition of note using GuzzleHTTP Client, Laravel Framework, and PHP language. Here's the following source code by which it starts working.
use GuzzleHttp\Client;
function insert_freshdesk_note($ticketId, $content, $attachments=null)
{
if(is_null($content)) {
return false;
}
$url = 'https://mydomain.freshdesk.com/api/v2/tickets/'.$ticketId.'/notes';
$method = 'POST';
$userName = config('freshdesk_api_key');
$password = 'password';
$attachmentsFilePath = explode('/',$attachments);
$fileName = end($attachmentsFilePath);
$options = (!empty($attachments)) ? [
'multipart' => [
[
'name' => 'body',
'contents' => $content,
],
[
'name' => 'private',
'contents' => "false",
],
[
'name' => 'attachments[]',
'contents' => fopen($attachments, 'r'),
'filename' => $fileName,
],
],
'auth' => [$userName, $password],
] : [
'json' => [
"body" => $content,
"private" => false,
],
'auth' => [$userName, $password]
];
$client = new Client();
try {
$response = $client->request($method, $url, $options);
return json_decode($response->getBody(), true);
} catch (Exception $e) {
Log::error($e);
}
}
We have to send the data in multipart fashion in order to Freshdesk backend to understand that data is there, by writing multipart/form-type in the header won't help. If you look at documentation also with and without attachments below:-
Without Attachment:-
curl -v -u user#yourcompany.com:test -H "Content-Type: application/json" -X POST -d '{ "body":"Hi tom, Still Angry", "private":false, "notify_emails":["tom#yourcompany.com"] }' 'https://domain.freshdesk.com/api/v2/tickets/3/notes'
With Attachment:-
curl -v -u user#yourcompany.com:test -F "attachments[]=#/path/to/attachment1.ext" -F "body=Hi tom, Still Angry" -F "notify_emails[]=tom#yourcompany.com" -X POST 'https://domain.freshdesk.com/api/v2/tickets/20/notes'
The difference in the curl can be seen.
This was the missing piece that I overlooked.
I am trying to send a request to RingCentral API. The link to documentation is https://developers.ringcentral.com/api-reference/Fax/createFaxMessage If I don't specify faxResolution or coverIndex everything goes well, fax could be sent. But if I add faxResolution param like in the code below, I receive error "Parameter [faxResolution] value is invalid", "errorCode" : "CMN-101". The same thing with coverIndex param. My client is GuzzleHttp 6.3
$token = $this->ringcentral->platform()->auth()->data()['access_token'];
$a = array();
foreach ($destination_numbers as $number) {
$a[] = [
'name' => 'to',
'contents' => $number,
'headers' => ['Content-Type' => 'multipart/form-data']
];
}
$a[] = [
'name' => 'faxResolution',
'contents' => 'High',
'headers' => ['Content-Type' => 'multipart/form-data']
];
foreach ($attachments as $attachment) {
$file_pointer = fopen($attachment, 'r');
$mime = mime_content_type($attachment);
$a[] = [
'name' => 'attachment',
'contents' => $file_pointer,
'headers' => ['Content-Type' => $mime]
];
}
$client = new Client();
try {
$response = $client->request('POST', url(config('services.ringcentral.app_url')) . '/restapi/v1.0/account/~/extension/~/fax', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $token
],
'multipart' => $a
]);
$response = json_decode($response->getBody(), true);
} catch (\GuzzleHttp\Exception\ClientException $e) {
echo($e->getResponse()->getBody()->getContents());
}
Here's what RingCentral suggests when using PHP. I included all of what they suggested, but just look at the part about faxResolution (2/3 of the way down)
<?php
// https://developers.ringcentral.com/my-account.html#/applications
// Find your credentials at the above url, set them as environment variables, or enter them below
// PATH PARAMETERS
$accountId = '<ENTER VALUE>';
$extensionId = '<ENTER VALUE>';
$recipient = '<ENTER VALUE>';
require('vendor/autoload.php');
$rcsdk = new RingCentral\SDK\SDK(getenv('clientId'), getenv('clientSecret'), getenv('serverURL'));
$platform = $rcsdk->platform();
$platform->login(getenv('username'), getenv('extension'), getenv('password'));
$request = $rcsdk->createMultipartBuilder()
->setBody(array(
'to' => array(array('phoneNumber' => $recipient)),
'faxResolution' => 'High',
))
->add(fopen('fax.jpg', 'r'))
->request("/restapi/v1.0/account/{$accountId}/extension/{$extensionId}/fax");
$r = $platform->sendRequest($request);
?>
So I have this class setup in laravel. It is using following header to initialize requests.
$this->xml = "<?xml version=\"1.0\"?>
<query xmlns=\"http://www.someurl.com/queryLanguage/v1.0\">
<logon>
<userName>".config('some.username')."</userName>
<password>".config('some.password')."</password>
<deviceName>".config('some.device')."</deviceName>
</logon>";
Then I have like 10 requests to make to the same url with above auth details.
so im doing it like.
$xml1 = $this->xml;
$xml1 .= "some xml";
$options = [
'headers' => [
'Content-Type' => 'text/xml; charset=UTF8',
],
'body' => $xml1,
];
$client = new Client();
$response = $client->request('POST', config('some.apiurl'), $options);
$xml2 = $this->xml;
$xml2 .= "some xml";
$options = [
'headers' => [
'Content-Type' => 'text/xml; charset=UTF8',
],
'body' => $xml2,
];
$client = new Client();
$response = $client->request('POST', config('some.apiurl'), $options);
$xml3 = $this->xml;
$xml3 .= "some xml";
$options = [
'headers' => [
'Content-Type' => 'text/xml; charset=UTF8',
],
'body' => $xml3,
];
$client = new Client();
$response = $client->request('POST', config('some.apiurl'), $options);
as you can see with each requests it makes a new login and eventually ended up getting too many concurrent logons error from remote server. so my question is how we use this api login information and just login once with guzzel and then use it for multiple requests later.
Thanks in advance.
You can use Guzzle CookieJar to save your session and send it to the next request.
http://docs.guzzlephp.org/en/stable/quickstart.html#cookies
#Request-1
$login = $client->request("POST" , $url , [
"headers" => $header,
"body" => $xmlLogin
]);
// Here you should get all cookies from $login request and save it to $tmpCookieJar variable for example.
// For request-2 it will depends on the requirement of the endpoint or api.
#Request-2
$action2 = $client->request("POST" , $url , [
"headers" => $header,
"body" => $xmlLogin, // If necessary
"cookies" => $tmpCookieJar
]);
Does anybody know the correct way to post JSON using Guzzle?
$request = $this->client->post(self::URL_REGISTER,array(
'content-type' => 'application/json'
),array(json_encode($_POST)));
I get an internal server error response from the server. It works using Chrome Postman.
For Guzzle 5, 6 and 7 you do it like this:
use GuzzleHttp\Client;
$client = new Client();
$response = $client->post('url', [
GuzzleHttp\RequestOptions::JSON => ['foo' => 'bar'] // or 'json' => [...]
]);
Docs
The simple and basic way (guzzle6):
$client = new Client([
'headers' => [ 'Content-Type' => 'application/json' ]
]);
$response = $client->post('http://api.com/CheckItOutNow',
['body' => json_encode(
[
'hello' => 'World'
]
)]
);
To get the response status code and the content of the body I did this:
echo '<pre>' . var_export($response->getStatusCode(), true) . '</pre>';
echo '<pre>' . var_export($response->getBody()->getContents(), true) . '</pre>';
For Guzzle <= 4:
It's a raw post request so putting the JSON in the body solved the problem
$request = $this->client->post(
$url,
[
'content-type' => 'application/json'
],
);
$request->setBody($data); #set body!
$response = $request->send();
This worked for me (using Guzzle 6)
$client = new Client();
$result = $client->post('http://api.example.com', [
'json' => [
'value_1' => 'number1',
'Value_group' =>
array("value_2" => "number2",
"value_3" => "number3")
]
]);
echo($result->getBody()->getContents());
$client = new \GuzzleHttp\Client();
$body['grant_type'] = "client_credentials";
$body['client_id'] = $this->client_id;
$body['client_secret'] = $this->client_secret;
$res = $client->post($url, [ 'body' => json_encode($body) ]);
$code = $res->getStatusCode();
$result = $res->json();
You can either using hardcoded json attribute as key, or you can conveniently using GuzzleHttp\RequestOptions::JSON constant.
Here is the example of using hardcoded json string.
use GuzzleHttp\Client;
$client = new Client();
$response = $client->post('url', [
'json' => ['foo' => 'bar']
]);
See Docs.
$client = new \GuzzleHttp\Client(['base_uri' => 'http://example.com/api']);
$response = $client->post('/save', [
'json' => [
'name' => 'John Doe'
]
]);
return $response->getBody();
This works for me with Guzzle 6.2 :
$gClient = new \GuzzleHttp\Client(['base_uri' => 'www.foo.bar']);
$res = $gClient->post('ws/endpoint',
array(
'headers'=>array('Content-Type'=>'application/json'),
'json'=>array('someData'=>'xxxxx','moreData'=>'zzzzzzz')
)
);
According to the documentation guzzle do the json_encode
Solution for $client->request('POST',...
For those who are using $client->request this is how you create a JSON request:
$client = new Client();
$res = $client->request('POST', "https://some-url.com/api", [
'json' => [
'paramaterName' => "parameterValue",
'paramaterName2' => "parameterValue2",
]
'headers' => [
'Content-Type' => 'application/json',
]
]);
Guzzle JSON Request Reference
Php Version: 5.6
Symfony version: 2.3
Guzzle: 5.0
I had an experience recently about sending json with Guzzle. I use Symfony 2.3 so my guzzle version can be a little older.
I will also show how to use debug mode and you can see the request before sending it,
When i made the request as shown below got the successfull response;
use GuzzleHttp\Client;
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
"Content-Type" => "application/json"
];
$body = json_encode($requestBody);
$client = new Client();
$client->setDefaultOption('headers', $headers);
$client->setDefaultOption('verify', false);
$client->setDefaultOption('debug', true);
$response = $client->post($endPoint, array('body'=> $body));
dump($response->getBody()->getContents());
#user3379466 is correct, but here I rewrite in full:
-package that you need:
"require": {
"php" : ">=5.3.9",
"guzzlehttp/guzzle": "^3.8"
},
-php code (Digest is a type so pick different type if you need to, i have to include api server for authentication in this paragraph, some does not need to authenticate. If you use json you will need to replace any text 'xml' with 'json' and the data below should be a json string too):
$client = new Client('https://api.yourbaseapiserver.com/incidents.xml', array('version' => 'v1.3', 'request.options' => array('headers' => array('Accept' => 'application/vnd.yourbaseapiserver.v1.1+xml', 'Content-Type' => 'text/xml'), 'auth' => array('username#gmail.com', 'password', 'Digest'),)));
$url = "https://api.yourbaseapiserver.com/incidents.xml";
$data = '<incident>
<name>Incident Title2a</name>
<priority>Medium</priority>
<requester><email>dsss#mail.ca</email></requester>
<description>description2a</description>
</incident>';
$request = $client->post($url, array('content-type' => 'application/xml',));
$request->setBody($data); #set body! this is body of request object and not a body field in the header section so don't be confused.
$response = $request->send(); #you must do send() method!
echo $response->getBody(); #you should see the response body from the server on success
die;
--- Solution for * Guzzle 6 * ---
-package that you need:
"require": {
"php" : ">=5.5.0",
"guzzlehttp/guzzle": "~6.0"
},
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'https://api.compay.com/',
// You can set any number of default request options.
'timeout' => 3.0,
'auth' => array('you#gmail.ca', 'dsfddfdfpassword', 'Digest'),
'headers' => array('Accept' => 'application/vnd.comay.v1.1+xml',
'Content-Type' => 'text/xml'),
]);
$url = "https://api.compay.com/cases.xml";
$data string variable is defined same as above.
// Provide the body as a string.
$r = $client->request('POST', $url, [
'body' => $data
]);
echo $r->getBody();
die;
Simply use this it will work
$auth = base64_encode('user:'.config('mailchimp.api_key'));
//API URL
$urll = "https://".config('mailchimp.data_center').".api.mailchimp.com/3.0/batches";
//API authentication Header
$headers = array(
'Accept' => 'application/json',
'Authorization' => 'Basic '.$auth
);
$client = new Client();
$req_Memeber = new Request('POST', $urll, $headers, $userlist);
// promise
$promise = $client->sendAsync($req_Memeber)->then(function ($res){
echo "Synched";
});
$promise->wait();
I use the following code that works very reliably.
The JSON data is passed in the parameter $request, and the specific request type passed in the variable $searchType.
The code includes a trap to detect and report an unsuccessful or invalid call which will then return false.
If the call is sucessful then json_decode ($result->getBody(), $return=true) returns an array of the results.
public function callAPI($request, $searchType) {
$guzzleClient = new GuzzleHttp\Client(["base_uri" => "https://example.com"]);
try {
$result = $guzzleClient->post( $searchType, ["json" => $request]);
} catch (Exception $e) {
$error = $e->getMessage();
$error .= '<pre>'.print_r($request, $return=true).'</pre>';
$error .= 'No returnable data';
Event::logError(__LINE__, __FILE__, $error);
return false;
}
return json_decode($result->getBody(), $return=true);
}
The answer from #user3379466 can be made to work by setting $data as follows:
$data = "{'some_key' : 'some_value'}";
What our project needed was to insert a variable into an array inside the json string, which I did as follows (in case this helps anyone):
$data = "{\"collection\" : [$existing_variable]}";
So with $existing_variable being, say, 90210, you get:
echo $data;
//{"collection" : [90210]}
Also worth noting is that you might want to also set the 'Accept' => 'application/json' as well in case the endpoint you're hitting cares about that kind of thing.
Above answers did not worked for me somehow. But this works fine for me.
$client = new Client('' . $appUrl['scheme'] . '://' . $appUrl['host'] . '' . $appUrl['path']);
$request = $client->post($base_url, array('content-type' => 'application/json'), json_encode($appUrl['query']));