Guzzle and Unable to parse response into JSON - php

I have a little php api client with this method:
private function send($endpoint)
{
$headers = array();
$body = $this->xmlSerialiser->convertToXML($this->getQueue());
try {
$response = json_decode(
$this->guzzleClient->post(
$endpoint,
$headers, $body
)
->send()
->json()
);
} catch (\Guzzle\Http\Exception\BadResponseException $e) {
$response = array('Error' => $e->getMessage());
}
return $response;
}
I'm always receiving
Unable to parse response body into JSON: 4 (500 Internal Server Error)
I already tried to know an example of server response and seems to be fine:
echo (string) $this->guzzleClient->post(
$endpoint,
$headers, $body
)
->send()->getBody();
and this is the result:
<Messages xmlns="http://www.example.com/xxx/3.0">
<GetAccountResponse RequestType="GetAccount">
<AccountId>xxxx-xxx-xxx-xxxx-xxxx</AccountId>
<Token>xxxxxxxxxxxxxx/t3VkEJXC7f6b6G4yPJSZ5QfT2hdSQXUmi0e8cndSYLK4N7mswRHifzwGHLUJYHM17iGL8s=</Token>
</GetAccountResponse>

I answered myself
the Guzzle documentation says: json method -> Parse the JSON response body and return an array
so in my case I need to switch the json mehod to xml (cos the response is an xml).
Finally this is the result:
private function send($endpoint)
{
$headers = array();
$body = $this->xmlSerialiser->convertToXML($this->getQueue());
try {
$response = (array)(
$this->guzzleClient->post(
$endpoint,
$headers, $body
)
->send()
->xml()
);
} catch (\Guzzle\Http\Exception\BadResponseException $e) {
$response = array('Error' => $e->getMessage());
}
return $response;
}

Use following code.
$response->getBody()->getContents()

Related

Laravel guzzle get response

I am using laravel guzzle package for get response from this https://eos.greymass.com/v1/history/get_transaction url
$client = new Client();
try {
$response = $client->request('GET', 'https://eos.greymass.com/v1/history/get_transaction?id=18a20dbc34082451143c03ac54a2f24d06494d51e68f8fb1211ca0b63a53f37d');
}catch (ClientException $e) {
$response = $e->getResponse();
$responseBodyAsString = $response->getBody()->getContents();
return redirect()->back()->with('error', $responseBodyAsString);
}
if ($response->getStatusCode() != 200){
return redirect()->back()->with('error', 'Status code must be 200');
}
$body = $response->getBody();
return $body;
I get $body data properly, but when i tried to get $body->block_num then showing me this Undefined property: GuzzleHttp\Psr7\Stream::$block_num error
You have to decode the $response to get it as because it will convert json into an object
So for example:
$response = json_decode($client->request('GET', 'https://eos.greymass.com/v1/history/get_transaction?id=18a20dbc34082451143c03ac54a2f24d06494d51e68f8fb1211ca0b63a53f37d')->getBody(), true);
Try This! It will Help You

GuzzleHttp\Client 400 bad request on Laravel 5.5

I am sending a POST request to an API, Curl returns 200 and the correct response.
When Implementing with GuzzleHttp\Client, I get a 400 Bad request, what is wrong with my formatting.
here is my code using Laravel Returns 400 Bad Request:
$client = new Client();
$URI = 'http://api.example.com';
$params['headers'] = ['Content-Type' => 'application/json',
'apikey' => config('app._api_key'),
'debug' => true
];
$params['form_params'] = [
'sender' => 'Test_sender',
'recipient' => config('app.test_recipient'),
'message_body' => 'Test body'
];
return $response = $client->post($URI, $params);
Curl (Returns 200):
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'apikey: 212121212’ -d '{ "message_body": "test","sender": "2018","recipient": “4453424141” }' 'http://api.example.com'
Try the below code:
$client = new \GuzzleHttp\Client(['headers' => ['Content-Type' => 'application/json',
'apikey'=> config('app._api_key'),
'debug' => true
]
]);
$URI = 'http://api.example.com';
$body['sender']='Test_sender';
$body['recipient']=config('app.test_recipient');
$body['message_body']='Test body';
$body=json_encode($body);
$URI_Response = $client->request('POST',$URI,['body'=>$body]);
$URI_Response =json_decode($URI_Response->getBody(), true);
return $URI_Response;
Note: I would suggest you to handle error please refer GuzzleDocumentation
That is proper error handling:
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
try {
$response = $client->get(YOUR_URL, [
'connect_timeout' => 10
]);
// Here the code for successful request
} catch (RequestException $e) {
// Catch all 4XX errors
// To catch exactly error 400 use
if ($e->getResponse()->getStatusCode() == '400') {
echo "Got response 400";
}
// You can check for whatever error status code you need
} catch (\Exception $e) {
// There was another exception.
}
Implementation: http://guzzle.readthedocs.org/en/latest/quickstart.html
You can handle errors like this
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\RequestException;
use Exception;
try{
$client = new Client();
$response = $client->request('POST', $url,[
'headers' => $header,
'form_params' => $form-params
]);
$body = $response->getBody();
$status = 'true';
$message = 'Data found!';
$data = json_decode($body);
}catch(ClientException $ce){
$status = 'false';
$message = $ce->getMessage();
$data = [];
}catch(RequestException $re){
$status = 'false';
$message = $re->getMessage();
$data = [];
}catch(Exception $e){
$this->status = 'false';
$this->message = $e->getMessage();
$data = [];
}
return ['status'=>$status,'message'=>$message,'data'=>$data];

hotelbed API http error

Here below i have attached my api request
$apiKey = "XXXX";
$Secret = "XXX";
$endpoint = "https://api.test.hotelbeds.com/hotel-api/1.0/hotels";
$request = new http\Client\Request("POST",
$endpoint,
[ "Api-Key" => $apiKey,
"X-Signature" => $signature,
"Accept" => "application/xml" ]);
try
{ $client = new http\Client;
$client->enqueue($request)->send();
$response = $client->getResponse();
if ($response->getResponseCode() != 200) {
printf("%s returned '%s' (%d)\n",
$response->getTransferInfo("effective_url"),
$response->getInfo(),
$response->getResponseCode()
);
} else {
printf($response->getBody());
}
} catch (Exception $ex) {
printf("Error while sending request, reason: %s\n",$ex->getMessage());
}'
getting following error
Uncaught Error: Class 'http\Client\Request' not found in
You need to add a use statement.
use http\Client\Request;
$request = new Request(blah blah);
Of course I assume you are using Composer autoloader. If not, you will also need to require_once() the file.
You can try using cURL instead of pecl_http. Here is an example:
<?php
// Your API Key and secret
$apiKey = "yourApiKey";
$Secret = "yourSecret";
// Signature is generated by SHA256 (Api-Key + Secret + Timestamp (in seconds))
$signature = hash("sha256", $apiKey.$Secret.time());
$endpoint = "https://api.test.hotelbeds.com/hotel-api/1.0/status";
echo "Your API Key is: " . $apiKey . "<br>";
echo "Your X-Signature is: " . $signature . "<br><br>";
// Example of call to the API
try
{
// Get cURL resource
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $endpoint,
CURLOPT_HTTPHEADER => ['Accept:application/json' , 'Api-key:'.$apiKey.'', 'X-Signature:'.$signature.'']
));
// Send the request & save response to $resp
$resp = curl_exec($curl);
// Check HTTP status code
if (!curl_errno($curl)) {
switch ($http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE)) {
case 200: # OK
echo "Server JSON Response:<br>" . $resp;
break;
default:
echo 'Unexpected HTTP code: ', $http_code, "\n";
echo $resp;
}
}
// Close request to clear up some resources
curl_close($curl);
} catch (Exception $ex) {
printf("Error while sending request, reason: %s\n",$ex->getMessage());
}
?>
Just make sure that first you uncomment ;extension=php_curl.dll in your php.ini file and restart your server.
We are planning to update our examples in the developer portal because some are outdated or not well documented.

looping through json data from url using php

Hi I am attempting to echo out data returned from an api I'm working with utilizing the following code:
<?php
ini_set("include_path", '/home/matthewt/php:' . ini_get("include_path") );
// This sample uses the Apache HTTP client from HTTP Components
(http://hc.apache.org/httpcomponents-client-ga/)
require_once 'HTTP/Request2.php';
$url = $request->getUrl();
$headers = array(
// Request headers
'Ocp-Apim-Subscription-Key' => 'my_id',
);
$request->setHeader($headers);
$parameters = array(
// Request parameters
);
$url->setQueryVariables($parameters);
$request->setMethod(HTTP_Request2::METHOD_GET);
// Request body
$request->setBody("{body}");
try
{
$response = $request->send();
echo $response->getBody();
}
catch (HttpException $ex)
{
echo $ex;
}
Everything up until this point works great and returns json data that basically looks like this: (I shortened the amount of fields to save space)
[{"GameID":49810,"Season":2017},{"GameID":49811,"Season":2017}]
What I need to know is how to loop through this data to print out the results for each game. I know I have to use something like this:
$arr = json_decode();
foreach($arr as $item) { //foreach element in $arr
$game_id = $item['GameID']; //etc
}
But I'm not sure what needs to be decoded...is it $response ?
Thanks
If $response->getBody() contains your json, then json_decode it, then this will be your array of objects which you can loop over.
So try this:
// snip
try
{
$response = $request->send();
$arr = json_decode($response->getBody());
foreach((array) $arr as $item) { //foreach element in $arr
echo $item->GameID; //etc
echo $item->Season; //etc
}
}
catch (HttpException $ex)
{
echo $ex;
}

$response->getBody() is empty when testing Slim 3 routes with PHPUnit

I use the following method to dispatch a Slim app's route in my PHPUnit tests:
protected function dispatch($path, $method='GET', $data=array())
{
// Prepare a mock environment
$env = Environment::mock(array(
'REQUEST_URI' => $path,
'REQUEST_METHOD' => $method,
));
// Prepare request and response objects
$uri = Uri::createFromEnvironment($env);
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new RequestBody();
// create request, and set params
$req = new Request($method, $uri, $headers, $cookies, $serverParams, $body);
if (!empty($data))
$req = $req->withParsedBody($data);
$res = new Response();
$this->headers = $headers;
$this->request = $req;
$this->response = call_user_func_array($this->app, array($req, $res));
}
For example:
public function testGetProducts()
{
$this->dispatch('/products');
$this->assertEquals(200, $this->response->getStatusCode());
}
However, as much as things like the status code and header are in the response, (string) $response->getBody() is empty so I cannot check for the presence of elements in the HTML. When I run the same route in the browser, I get the expected HTML output. Also, if I echo $response->getBody(); exit; and then view the output in the browser, I see HTML body. Is there any reason, with my implementation, I'm not seeing this in the my tests? (in the CLI, so different environment I guess)
$response->getBody() will be empty as you've set up the parsed body. It's easier to put it into the RequestBody as a string in the same way as it would be set if it came in over the wire.
i.e something like this:
protected function dispatch($path, $method='GET', $data=array())
{
// Prepare a mock environment
$env = Environment::mock(array(
'REQUEST_URI' => $path,
'REQUEST_METHOD' => $method,
'CONTENT_TYPE' => 'application/json',
));
// Prepare request and response objects
$uri = Uri::createFromEnvironment($env);
$headers = Headers::createFromEnvironment($env);
$cookies = [];
$serverParams = $env->all();
$body = new RequestBody();
if (!empty($data)) {
$body->write(json_encode($data));
}
// create request, and set params
$req = new Request($method, $uri, $headers, $cookies, $serverParams, $body);
$res = new Response();
$this->headers = $headers;
$this->request = $req;
$this->response = call_user_func_array($this->app, array($req, $res));
}

Categories