actually i want to validate given token .. the validate code written in another lumen package. i have got some issues when i send request to validate token. i dont know why it's not working. cant use another api inside lumen ?
if i use that check token api in postman https://i.stack.imgur.com/kSpJt.png. it works fine. it's thrown error when i call that api inside other lumen package
this is what i got when use this api in postman https://i.stack.imgur.com/hfFzk.png
error log https://i.stack.imgur.com/ds0oR.png
<?php
namespace App\Helpers;
use App\Helpers\ResponseBuilder;
class check_customer_token_verification
{
public static function check($token, $vendor_id)
{
$client = new \GuzzleHttp\Client();
$result = $client->post('dev.adiswar-crm.local/customer/crm/v-1-0-0/check-token', [
'form_params' => [
'token' => isset($token)?$token:'',
'vendor_id' => $vendor_id,
]
]);
$res_data = json_decode($result->getBody()->getContents()); dd($res_data);
if ($res_data->http_code == 401) {
return ResponseBuilder::responseResult(400, $res_data->message);
}
return $res_data;
}
} ```
dump this api in postman. i got issue which is below
^ {#120
+"http_code": 400
+"message": """
Server error: `POST dev.adiswar-crm.local/customer/crm/v-1-0-0/check-token` resulted in a `500 Internal Server Error` response:
<!DOCTYPE html>
<html>
<head>
<meta name="robots" content="noindex,nofollow" />
<style>
(truncated...)
"""
}```
You need to define your form_params, though your code can work but I would also suggest using try catch blocks and adding your 401 exception in catch block (& other 400 in there), see the changes I have made
public static function check($token, $vendor_id)
{
try{
$client = new \GuzzleHttp\Client();
define("form_params", \GuzzleHttp\RequestOptions::FORM_PARAMS );
$guzzleResponse = $client->post('dev.adiswar-crm.local/customer/crm/v-1-0-0/check-token', [
'form_params' => [
'token' => isset($token) && !empty($token) ? $token : '',
'vendor_id' => $vendor_id,
]
]);
if ($guzzleResponse->getStatusCode() == 200) {
$result = json_decode($guzzleResponse->getBody(),true);
// dd($result);
}
return $result;
}catch(\GuzzleHttp\Exception\RequestException $e){
// Catch all 4XX errors
dd($e->getMessage, $e->getTraceAsString());
// To catch exactly error 401 use
if ($e->hasResponse()){
if ($e->getResponse()->getStatusCode() == '401') {
return ResponseBuilder::responseResult(400, $e->getMessage());
}
}
}catch(Exception $e){
//other errors
}
}
Related
So im new to guzzle and building API's , I have used Laravel Passport and on one GET call its fine. I have written a POST call and getting a 500 error in return
Post function
public function newsSingle() {
$request = (new GuzzleHttp\Client)->post('http://138.68.180.100/news/article/single', [
'headers' => [
'Authorization' => 'Bearer '.session()->get('token.access_token'),
'post_id' => $_POST['post_id']
]
]);
$news = json_decode((string)$request->getBody());
return view('pages.newsingle', compact('news'));
}
Which does add the post item
POST Data
post_id
"3"
on the other end I have
Route:
Route::post('news/article/single', 'ApiController#singlePost')->middleware('auth:api');
Controller function:
public function singlePost(Request $request) {
$article = Articles::where('id', $request['post_id'])->get();
return $article;
}
my error:
Server error: `POST http://ipaddress/news/article/single` resulted in a `500 Internal Server Error` response: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta name="robots" content="noindex,nofollow (truncated...)
We found the similar issue with Guzzle for External API calls when response code is 500 and got Server error: and exception is thrown. There is a work around to do a bypass mechanism by catching the exception due to BadResponseException to return as response. below is the code for performing this. :)
catch (\GuzzleHttp\Exception\BadResponseException $e) {
return $e->getResponse()->getBody()->getContents();
}
I connecting to API by Guzzle:
$client = new Client();
try {
$res = $client->post( 'xxx' . $this->url , [
'headers' => $headers,
'json' => $data,
]);
} catch( Exception $e ) {
echo json_decode( $e->getResponse()->getBody(), true );
}
And it's working but when it's 'catch', I need to get code from response but I getting:
Server error: `POST XXXXX` resulted in a `555 Error` response: {"status":"ERROR","errors":[{"message":"Subscribers already exists in this subscribers list","code":1304}]}
And I can't get the code. How to do this?
UPDATE
Here is screen with full response.
Just extract the response from the exception. Guzzle throws a special BadResponseException in case of failure, so take a look at this class.
try {
// ...
} catch (BadResponseException $exception) {
// 555
$exception->getCode();
$appError = json_decode(
$exception->getResponse()->getBody()->getContents(),
true
);
// 1304
$appErrorCode = $appError['errors'][0]['code'];
}
i have a function im testing which suppose to return error 500 but after adding 'http_errors' => 'false' to the put definition, the returned error changes from 500 to 404.
this is my function:
public function testApiAd_updateWithIllegalGroupId($adId)
{
$client = new Client(['base_uri' => self::$base_url]);
try {
$response = $client->put(self::$path.$adId, ['form_params' => [
'name' => 'bellow content - guzzle testing',
'description' => 'guzzle testing ad - demo',
'group_id' => '999999999',
]]);
} catch (Guzzle\Http\Exception\BadResponseException $e) {
//Here i want to compare received error to 500
}
}
right now this function will return server error: 500 but it also stops the class from executing rest of the tests and i can't assert it.
how can i use the guzzle getStatusCode() in my function while getting error 500 and not 404 as i mentioned above
The BadResponseException contains the original Request and the Response object. So you can, the catch block the following assertion:
} catch (Guzzle\Http\Exception\BadResponseException $e) {
//Here i want to compare received error to 500
$responseCode = $e->getResponse()->getStatusCode();
$this->assertEquals(500, $responseCode, "Server Error");
}
Further info in the doc
function order_confirmationAction($order,$token) {
$client = new \GuzzleHttp\Client();
$answer = $client->post("http://www.fullcommerce.com/rest/public/Qtyresponse",
array('body' => $order)
);
$answer = json_decode($answer);
if ($answer->status=="ACK") {
return $this->render('AcmeDapiBundle:Orders:ack.html.twig', array(
'message' => $answer->message,
));
} else throw new \Symfony\Component\HttpKernel\Exception\HttpException(500, $answer->message);
}
If $client->post() response status code is an "Error 500" Symfony stops the script execution and throw new exception before the json decoding.
How can I force Symfony to ignore $client->post() bad response and execute till the last if statement?
$client = new \GuzzleHttp\Client();
try {
$answer = $client->post("http://www.fullcommerce.com/rest/public/Qtyresponse",
array('body' => $serialized_order)
);
}
catch (\GuzzleHttp\Exception\ServerException $e) {
if ($e->hasResponse()) {
$m = $e->getResponse()->json();
throw new \Symfony\Component\HttpKernel\Exception\HttpException(500, $m['result']['message']);
}
}
I solved like this. In that way I can access to responses of remote server even if it returns an error 500 code.
Per Guzzle documentation:
Guzzle throws exceptions for errors that occur during a transfer.
Specifically, if the API responds with a 500 HTTP error, you shouldn't expect its content to be JSON, and you don't want to parse it, so you're better off re-throwing an exception from there already (or informing the user that something went wrong). I would suggest trying this out:
function order_confirmationAction($order, $token) {
$client = new \GuzzleHttp\Client();
try {
$answer = $client->post("http://www.fullcommerce.com/rest/public/Qtyresponse",
array('body' => $order)
);
}
catch (Exception $e) {
throw new \Symfony\Component\HttpKernel\Exception\HttpException(500, $e->getMessage());
}
$answer = json_decode($answer);
if ($answer->status=="ACK") {
return $this->render('AcmeDapiBundle:Orders:ack.html.twig', array(
'message' => $answer->message,
));
} else {
throw new \Symfony\Component\HttpKernel\Exception\HttpException(500, $answer->message);
}
}
It is probably also a good idea to check for errors when JSON-decoding the response, because there could be surprises in the content you're getting (eg. wrong format, missing or unexpected fields or values, etc.).
I'm trying to catch exceptions from a set of tests I'm running on an API I'm developing and I'm using Guzzle to consume the API methods. I've got the tests wrapped in a try/catch block but it is still throwing unhandled exception errors. Adding an event listener as described in their docs doesn't seem to do anything. I need to be able to retrieve the responses that have HTTP codes of 500, 401, 400, in fact anything that isn't 200 as the system will set the most appropriate code based on the result of the call if it didn't work.
Current code example
foreach($tests as $test){
$client = new Client($api_url);
$client->getEventDispatcher()->addListener('request.error', function(Event $event) {
if ($event['response']->getStatusCode() == 401) {
$newResponse = new Response($event['response']->getStatusCode());
$event['response'] = $newResponse;
$event->stopPropagation();
}
});
try {
$client->setDefaultOption('query', $query_string);
$request = $client->get($api_version . $test['method'], array(), isset($test['query'])?$test['query']:array());
// Do something with Guzzle.
$response = $request->send();
displayTest($request, $response);
}
catch (Guzzle\Http\Exception\ClientErrorResponseException $e) {
$req = $e->getRequest();
$resp =$e->getResponse();
displayTest($req,$resp);
}
catch (Guzzle\Http\Exception\ServerErrorResponseException $e) {
$req = $e->getRequest();
$resp =$e->getResponse();
displayTest($req,$resp);
}
catch (Guzzle\Http\Exception\BadResponseException $e) {
$req = $e->getRequest();
$resp =$e->getResponse();
displayTest($req,$resp);
}
catch( Exception $e){
echo "AGH!";
}
unset($client);
$client=null;
}
Even with the specific catch block for the thrown exception type I am still getting back
Fatal error: Uncaught exception 'Guzzle\Http\Exception\ClientErrorResponseException' with message 'Client error response [status code] 401 [reason phrase] Unauthorized [url]
and all execution on the page stops, as you'd expect. The addition of the BadResponseException catch allowed me to catch 404s correctly, but this doesn't seem to work for 500 or 401 responses. Can anyone suggest where I am going wrong please.
Depending on your project, disabling exceptions for guzzle might be necessary. Sometimes coding rules disallow exceptions for flow control. You can disable exceptions for Guzzle 3 like this:
$client = new \Guzzle\Http\Client($httpBase, array(
'request.options' => array(
'exceptions' => false,
)
));
This does not disable curl exceptions for something like timeouts, but now you can get every status code easily:
$request = $client->get($uri);
$response = $request->send();
$statuscode = $response->getStatusCode();
To check, if you got a valid code, you can use something like this:
if ($statuscode > 300) {
// Do some error handling
}
... or better handle all expected codes:
if (200 === $statuscode) {
// Do something
}
elseif (304 === $statuscode) {
// Nothing to do
}
elseif (404 === $statuscode) {
// Clean up DB or something like this
}
else {
throw new MyException("Invalid response from api...");
}
For Guzzle 5.3
$client = new \GuzzleHttp\Client(['defaults' => [ 'exceptions' => false ]] );
Thanks to #mika
For Guzzle 6
$client = new \GuzzleHttp\Client(['http_errors' => false]);
To catch Guzzle errors you can do something like this:
try {
$response = $client->get('/not_found.xml')->send();
} catch (Guzzle\Http\Exception\BadResponseException $e) {
echo 'Uh oh! ' . $e->getMessage();
}
... but, to be able to "log" or "resend" your request try something like this:
// Add custom error handling to any request created by this client
$client->getEventDispatcher()->addListener(
'request.error',
function(Event $event) {
//write log here ...
if ($event['response']->getStatusCode() == 401) {
// create new token and resend your request...
$newRequest = $event['request']->clone();
$newRequest->setHeader('X-Auth-Header', MyApplication::getNewAuthToken());
$newResponse = $newRequest->send();
// Set the response object of the request without firing more events
$event['response'] = $newResponse;
// You can also change the response and fire the normal chain of
// events by calling $event['request']->setResponse($newResponse);
// Stop other events from firing when you override 401 responses
$event->stopPropagation();
}
});
... or if you want to "stop event propagation" you can overridde event listener (with a higher priority than -255) and simply stop event propagation.
$client->getEventDispatcher()->addListener('request.error', function(Event $event) {
if ($event['response']->getStatusCode() != 200) {
// Stop other events from firing when you get stytus-code != 200
$event->stopPropagation();
}
});
thats a good idea to prevent guzzle errors like:
request.CRITICAL: Uncaught PHP Exception Guzzle\Http\Exception\ClientErrorResponseException: "Client error response
in your application.
In my case I was throwing Exception on a namespaced file, so php tried to catch My\Namespace\Exception therefore not catching any exceptions at all.
Worth checking if catch (Exception $e) is finding the right Exception class.
Just try catch (\Exception $e) (with that \ there) and see if it works.
If the Exception is being thrown in that try block then at worst case scenario Exception should be catching anything uncaught.
Consider that the first part of the test is throwing the Exception and wrap that in the try block as well.
You need to add a extra parameter with http_errors => false
$request = $client->get($url, ['http_errors' => false]);
I want to update the answer for exception handling in Psr-7 Guzzle, Guzzle7 and HTTPClient(expressive, minimal API around the Guzzle HTTP client provided by laravel).
Guzzle7 (same works for Guzzle 6 as well)
Using RequestException, RequestException catches any exception that can be thrown while transferring requests.
try{
$client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Bearer ' . $token]]);
$guzzleResponse = $client->get('/foobar');
// or can use
// $guzzleResponse = $client->request('GET', '/foobar')
if ($guzzleResponse->getStatusCode() == 200) {
$response = json_decode($guzzleResponse->getBody(),true);
//perform your action with $response
}
}
catch(\GuzzleHttp\Exception\RequestException $e){
// you can catch here 400 response errors and 500 response errors
// You can either use logs here use Illuminate\Support\Facades\Log;
$error['error'] = $e->getMessage();
$error['request'] = $e->getRequest();
if($e->hasResponse()){
if ($e->getResponse()->getStatusCode() == '400'){
$error['response'] = $e->getResponse();
}
}
Log::error('Error occurred in get request.', ['error' => $error]);
}catch(Exception $e){
//other errors
}
Psr7 Guzzle
use GuzzleHttp\Psr7;
use GuzzleHttp\Exception\RequestException;
try {
$client->request('GET', '/foo');
} catch (RequestException $e) {
$error['error'] = $e->getMessage();
$error['request'] = Psr7\Message::toString($e->getRequest());
if ($e->hasResponse()) {
$error['response'] = Psr7\Message::toString($e->getResponse());
}
Log::error('Error occurred in get request.', ['error' => $error]);
}
For HTTPClient
use Illuminate\Support\Facades\Http;
try{
$response = Http::get('http://api.foo.com');
if($response->successful()){
$reply = $response->json();
}
if($response->failed()){
if($response->clientError()){
//catch all 400 exceptions
Log::debug('client Error occurred in get request.');
$response->throw();
}
if($response->serverError()){
//catch all 500 exceptions
Log::debug('server Error occurred in get request.');
$response->throw();
}
}
}catch(Exception $e){
//catch the exception here
}
Old question, but Guzzle adds the response within the exception object. So a simple try-catch on GuzzleHttp\Exception\ClientException and then using getResponse on that exception to see what 400-level error and continuing from there.
I was catching GuzzleHttp\Exception\BadResponseException as #dado is suggesting. But one day I got GuzzleHttp\Exception\ConnectException when DNS for domain wasn't available.
So my suggestion is - catch GuzzleHttp\Exception\ConnectException to be safe about DNS errors as well.
If you are using the latest version say 6^ and you have a JSON parameter, you can add 'http_errors' => false to the array together with the JSON as seen below
I was looking out for away to do this i.e with my JSON in there but couldn't find a straight answer.