Handling Client Errors exceptions on GuzzleHttp - laravel

im trying to handdle request status code, basically checking if the status is 200, in case that it isnt handle it. Im using a package called "GuzzleHttp\Client", when there is a 404 it gives me a error:
Client error: `GET https://api.someurl---` resulted in a `404 Not Found` response:
{"generated_at":"2017-09-01T16:59:25+00:00","schema":"","message":"No events scheduled for this date."}
But than in the screen is displayed in a format that i want to change, so im trying to catch and give a different output on the view. But is not working, it stills gives me the red screen error.
try {
$client = new \GuzzleHttp\Client();
$request = $client->request('GET', $url);
$status = $request->getStatusCode();
if($status == 200){
return $status;
}else{
throw new \Exception('Failed');
}
} catch (\GuzzleHttp\Exception\ConnectException $e) {
//Catch errors
return $e->getStatusCode();
}

Okay so if you want to stick with a try-catch you want to do something like this:
$client = new \GuzzleHttp\Client();
try {
$request = $client->request('GET', $url);
} catch (\GuzzleHttp\Exception\ConnectException $e) {
// This is will catch all connection timeouts
// Handle accordinly
} catch (\GuzzleHttp\Exception\ClientException $e) {
// This will catch all 400 level errors.
return $e->getResponse()->getStatusCode();
}
$status = $request->getStatusCode();
If the catch doesn't get triggered the $request would be successful meaning it'll have a status code of 200.
However to to catch the 400 error, ensure you've got http_errors request option is set to true when setting up the $client.

Related

Why does Laravel Cashier silently catch Stripe exceptions?

There are numerous places in Laravel Cashier where exceptions are trapped within the Cashier code, but not really handled in any meaningful way - not even logged. This results in bizarre behaviour if there is something wrong with the Stripe request (e.g. invalid price_id specified), where a null value is returned with no indication about why.
Anyone know why they have silently 'trapped' these errors making it impossible for the calling code to report?
e.g. Laravel\Cashier\Concerns\ManageInvoices::upcomingInvoice():
public function upcomingInvoice(array $options = [])
{
if (! $this->hasStripeId()) {
return;
}
$parameters = array_merge([
'automatic_tax' => $this->automaticTaxPayload(),
'customer' => $this->stripe_id,
], $options);
try {
$stripeInvoice = $this->stripe()->invoices->upcoming($parameters);
return new Invoice($this, $stripeInvoice, $parameters);
} catch (StripeInvalidRequestException $exception) {
//
}
}

How can I handle a custom HTTP exception?

I created an exception called invalid balance, and I'm using like the following. My output result status is 500. How can I change this status to 400?
try {
$balance = Wallet::findOrFail()->docs()
->sum('amount');
if ($balance == 0) {
throw new InvalidBalance();
}
} catch (QueryException $e) {
$message = Str::contains($e->getMessage(), 'Deadlock') ?
'Server is busy' : $e->getMessage();
throw new HttpException(400, $message);
} catch (\Exception $e) {
throw $e;
}
You can use the abort helper.
if ($balance === 0)
{
abort(400, 'Bad Request.');
}
Or within the InvalidBalance class do the abort there.
You can use response() method and pass the http status code as the second parameter as in laravel helpers functions
return response()->json(['message'=>'your message'], 400);

Error logging is truncated in Laravel of Guzzle http

Guzzle http is truncating exceptions with more than 120 characters, but I need to log the full exception message. How can I do this?
I am using laravel 4.2.22.
try {
// whatever
} catch (\GuzzleHttp\Exception\RequestException $ex) {
return $ex->getResponse()->getBody()->getContents();
// you can even json_decode the response like json_decode($ex->getResponse()->getBody()->getContents(), true)
}
It is the same for Laravel 5 and 4
try {
$response = $client->post($path, $params);
} catch (\GuzzleHttp\Exception\RequestException $ex) {
\Log::debug('error');
\Log::debug((string) $ex->getResponse()->getBody());
throw $ex;
}
if you just go to $ex->getMessage(), you will get
(truncated...)
at the end.
Might be better solution:
try {
// do request here like:
// return $client->post($path, $params);
} catch (\GuzzleHttp\Exception\ServerException $ex) {
$exFactoryWithFullBody = new class('', $ex->getRequest()) extends \GuzzleHttp\Exception\RequestException {
public static function getResponseBodySummary(ResponseInterface $response)
{
return $response->getBody()->getContents();
}
};
throw $exFactoryWithFullBody->create($ex->getRequest(), $ex->getResponse());
}

Laravel and jwt-auth - how to check if the user is logged in

I have set up Laravel with jwt (using jwt-auth). In my Kernel.php - $routeMiddleware I have added :
'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class,
'jwt.refresh' => \Tymon\JWTAuth\Middleware\RefreshToken::class
As I understand it 'jwt.refresh' will automatically refresh / create a new token for the user for each request.
In my single page ajax app I need to check if the user is logged in so I have added a route that calls this function:
public function isAuthenticated() {
$token = JWTAuth::getToken();
if(!$token){
throw new JWTException('Token not provided');
}
try{
$token = JWTAuth::refresh($token);
}catch(TokenInvalidException $e){
throw new AccessDeniedHttpException('The token is invalid');
}
return $this->response->withArray(['token'=>$token]);
}
The problem is that when isAuthenticated() is called the JWTAuth::refresh($token) call fails.
I guess it has something to do with that the token is refreshed.
What I want to do is to return true if the client's token is valid.
Is there a way to do this?
Removing 'jwt-refresh' seems to not solve the issue for us.
Thank you in advance!
My first observation is, where is the token stored? Is it parsed with the request? Because I believe that if your app uses jwt with api, then each request should have a token to signify a logged in user so something like this would be helpful:
try {
if (! $token = JWTAuth::parseToken()) {
//throw an exception
}
} catch (Exception $e) {
if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){
//throw an exception
}else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){
//throw an exception
} else if ( $e instanceof \Tymon\JWTAuth\Exceptions\JWTException) {
//throw an exception
}else{
//throw an exception
}
}
If successfully parsed from the request, then:
$user = JWTAuth::toUser($token);
see: https://github.com/tymondesigns/jwt-auth/wiki/Authentication
With your example code, if the token is not set - nothing is retrieved. However, if you want session based authentication, why not use the default authentication from Laravel.
Hope this helps :)
You can get the current user related to token and check if not null:
$user = JWTAuth::setToken($token)->toUser();
if($user == null){
abort(401);
}

How to handle native exception in Laravel?

For example, I use:
return User::findOrFail($id);
When row does not exist with $id I get exception.
How I can return this exception in Json response? It returns HTML Laravel page now.
I need something like as:
{"error", "No query results for model"}
From their documentation:
Sometimes you may wish to throw an exception if a model is not found. This is particularly useful in routes or controllers. The findOrFail and firstOrFail methods will retrieve the first result of the query. However, if no result is found, a Illuminate\Database\Eloquent\ModelNotFoundException will be thrown.
So, you can either catch that exception, or go with the simple Find method. It will return false if not found, so you can handle it accordingly.
return User::find($id);
UPDATE:
Option 1:
try {
return User::findOrFail($id);
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
return json_encode(['error' => 'No query results for model']);
}
Option 2:
$user = User::find($id);
if($user) {
return $user;
}
return json_encode(['error' => 'No query results for model']);
You can handle various types of exceptions, that exception can be handle with a ModelNotFoundException in this case
try{
$user = User::findOrFail($id);
}catch(ModelNotFoundException $e){
return response()->json(['error' => 'User not found'], 400);
}
And there's another way to catch various types of exceptions in the Handler.php located on app/Exceptions/Handler.php there you can catch the exceptions and return whatever you want inside the render function.
For example insede that function you can add this before the return parent::render($request, $e):
if($e instanceof ModelNotFoundException)
{
return new Response(['message' => 'We haven\'t find any data'], 204);
}
You should look in render method of Handler file. You can test exception class here and depending on it return different response in Json format

Resources