I'm trying to catch errors that occur during HTTP client operations. If debugging is enabled APP_DEBUG=true then I get an error trace, if it is off, then it comes json response "message": "Server Error". But I need to catch exceptions, it doesn't work. Tried catch (\Illuminate\Http\Client\ConnectionException $e), but it didn't work. What am I doing wrong?
public function ExampleMethod()
{
try {
$response =
Http::withBasicAuth(env('REMOTE_LOGIN'), env('REMOTE_PASSWORD'))
->accept('application/json')
->retry(3, 2000)->timeout(12)
->withBody("dummy body content", "application/json")
->post($host . $url);
if ($response->ok()) {
//Do something
}
} catch (Exception $e) {
dd("CATCH IT");
}
}
There is an example from the documentation, the domain does not exist, and an exception handler should work somewhere, but it does not work
public function catchExceptins()
{
try {
$url = "domain-is-not-exist.com";
$response = Http::get($url);
if ($response->ok()) {
dd("200 OK");
}
//
if($response->failed()){
dd("FAILED");
}
//Below are the handlers that should work,
//but they do not respond when there is no domain
//or for example if the server response is 505
if($response->serverError()) {
dd("FAILED");
}
if($response->clientError()) {
dd("FAILED");
}
$response->throw(function($response, $e){
dd("FAILED");
})->json();
} catch (Exception $e) {
dd($e);
}
}
Laravel's HTTP client wrapper offers a mechanism for handling errors with a bunch of useful methods.
public function ExampleMethod()
{
try{
$response = Http::withBasicAuth(env('REMOTE_LOGIN'), env('REMOTE_PASSWORD'))
->accept('application/json')
->retry(3, 2000)->timeout(12)
->withBody("dummy body content", "application/json")
->post($host . $url);
//Check for any error 400 or 500 level status code
if($response->failed()){
// process the failure
}
//Check if response has error with 500 level status code
if($response->serverError()) {
//process on server error
}
//Check if response has error with 400 level status code
if($response->clientError()) {
//process on client error
}
// It also allows to throw exceptions on the $response
//If there's no error then the chain will continue and json() will be invoked
$response->throw(function($response, $e){
//do your thing
})->json();
}
catch(\Exception $e) {
//$e->getMessage() - will output "cURL error 6: Could not resolve host" in case of invalid domain
}
}
Laravel Docs - Http Client - Exception Handling
When you set APP_DEBUG=false, it just shows a generic error to the end user for security, but should give you the detailed error inside of the Laravel logs. 'All' APP_DEBUG=true does, is make the development process easier by displaying the log on the front end.
Your Laravel logs should be inside of "/storage/logs".
https://laravel.com/docs/9.x/configuration#debug-mode
https://laravel.com/docs/9.x/errors#configuration
Related
I'm currently building a single page application based on Laravel and VueJS.
Is there any better way then mine to handle errors with axios?
This is how I currently do it when a user clicks on login button:
VueTemplae:
methods : {
authenticateUser() {
axios.post('/api/login', this.form).then(() => {
this.$router.push({name : 'home'});
}).catch((error) => {
this.error = error.response.data.message;
});
}
}
Api route:
public function login() {
try {
// do validation
} catch(Exception) {
// validation failed
throw new Exception('login.failed');
}
// manually authentication
if(Auth::attempt(request()->only('email', 'password'))) {
return response()->json(Auth::user(), 200);
}
// something else went wrong
throw new Exception('login.failed');
}
Unfortunately, throwing an exception always prints an internal server error into the console.
If I return something else than an exception, axios always executes then().
Is there any way to prevent this or a better way to handle axios responses?
Thank you!
Your API needs to return a response with a 4XX status code in order for the catch block to fire in your Vue component.
Example:
After you catch the error on the API side, send a response with status code 400 Bad Request. It will be formatted similarly to your successful login response, but with an error message and 400 status code instead of 200.
I am adding CcAvenue gateway in laravel 5.3 on PHP 7.2, everything working fine till the payment page of CcAvenue, but after payment is done or payment canceled by the user, the return response URL is showing the following error
"Oops! An Error Occurred
The server returned a "405 Method Not Allowed".
Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused."
My return URL is this: https:// www.domainname.com/booking/cancel/cc_checkout_gateway?c=f4b7d25d6e894a44725fff59adafcf82
Code in the Routes file
use Illuminate\Support\Facades\Route;
// Booking
Route::group(['prefix'=>config('booking.booking_route_prefix')],function(){
Route::post('/addToCart','BookingController#addToCart');
Route::post('/doCheckout','BookingController#doCheckout')->name('booking.doCheckout');
Route::get('/confirm/{gateway}','BookingController#confirmPayment');
Route::get('/cancel/{gateway}','BookingController#cancelPayment');
Route::get('/{code}','BookingController#detail');
Route::get('/{code}/checkout','BookingController#checkout');
Route::get('/{code}/check-status','BookingController#checkStatusCheckout');
//ical
Route::get('/export-ical/{type}/{id}','BookingController#exportIcal')->name('booking.admin.export-ical');
//inquiry
Route::post('/addEnquiry','BookingController#addEnquiry');
});
Route::group(['prefix'=>'gateway'],function(){
Route::get('/confirm/{gateway}','NormalCheckoutController#confirmPayment')->name('gateway.confirm');
Route::get('/cancel/{gateway}','NormalCheckoutController#cancelPayment')->name('gateway.cancel');
Route::get('/info','NormalCheckoutController#showInfo')->name('gateway.info');
});
Code in BookingController.php
public function cancelPayment(Request $request, $gateway)
{
$gateways = get_payment_gateways();
if (empty($gateways[$gateway]) or !class_exists($gateways[$gateway])) {
return $this->sendError(__("Payment gateway not found"));
}
$gatewayObj = new $gateways[$gateway]($gateway);
if (!$gatewayObj->isAvailable()) {
return $this->sendError(__("Payment gateway is not available"));
}
return $gatewayObj->cancelPayment($request);
}
Code in Gateway CcCheckoutGateway.php
public function cancelPayment(Request $request)
{
$c = $request->query('c');
$booking = Booking::where('code', $c)->first();
if (!empty($booking) and in_array($booking->status, [$booking::UNPAID])) {
$payment = $booking->payment;
if ($payment) {
$payment->status = 'cancel';
$payment->logs = \GuzzleHttp\json_encode([
'customer_cancel' => 1
]);
$payment->save();
// Refund without check status
$booking->tryRefundToWallet(false);
}
return redirect($booking->getDetailUrl())->with("error", __("You cancelled the payment"));
}
if (!empty($booking)) {
return redirect($booking->getDetailUrl());
} else {
return redirect(url('/'));
}
}
After too much R&D I found that my routes code is allowing method is GET & HEAD, but Ccavenue response URL is sending the response in POST method
I have tried every possible solution changed
Route::get('/cancel/{gateway}','BookingController#cancelPayment');
to
Route::post('/cancel/{gateway}','BookingController#cancelPayment');
and
Route::any('/cancel/{gateway}','BookingController#cancelPayment');
but after that it showing error 419: page expired
Please tell me how can I resolve the above issue.
In my front end application, I have to handle the error response of the HTTP REST call.
Front end:
restservice.check().subscribe(
response => {
if (response != null) {
},
error => {
if (error instanceof Error) {
}}
});
Controller.java
public ResponseEntity updateEstablishment
{
return new ResponseEntity<>(obj, HttpStatus.OK);
}
How can I return an instance of Error here.
REST services should catch and handle internal exception. And should return meaningful error code and message back to client. Please find below link to best way to handle exception in REST
https://www.baeldung.com/rest-api-error-handling-best-practices
I implement search functionalities with the help of solr via solarium in CodeIgniter.
I'm starting my website without solr connection (i.e. If the solr connection is stopped), My website throws the below warning message,
An uncaught Exception was encountered
Type: Solarium\Exception\HttpException
Message: Solr HTTP error: HTTP request failed, Failed to connect to localhost port 8983: Connection refused
Filename: C:\wamp\www\project-folder\project-name\vendor\solarium\solarium\src\Core\Client\Adapter\Curl.php
Line Number: 170
My doubt is if any chance to add exception handling in solr connection.
That means, If solr status is true it works as it is. If the solr status is false (Not in connection) the error warning is not displayed.
This above scenario is possible or not by using exception handling.
Update
My controller page,
function __construct()
{
parent::__construct();
$this->config->load('solarium');
$this->client = new Solarium\Client($this->config->item('solarium_endpoint'));
}
public function solrQuery()
{
$query = $this->client->createSelect();
$query->setStart(0)->setRows(1000);
// get the facetset component
$facetSet = $query->getFacetSet();
$facetSet->createFacetField('product_category_1')->setField('product_category_1');
$categories_data = $this->client->select($query);
}
Surround the relevant bits of code that throw exceptions in a try-catch block like so:
function __construct() {
parent::__construct();
$this->config->load('solarium');
try {
$this->client = new Solarium\Client($this->config->item('solarium_endpoint'));
} catch (\Exception $e) {
show_error($e->getMessage());
}
}
public function solrQuery() {
try {
$query = $this->client->createSelect();
$query->setStart(0)->setRows(1000);
// get the facetset component
$facetSet = $query->getFacetSet();
$facetSet->createFacetField('product_category_1')->setField('product_category_1');
$categories_data = $this->client->select($query);
} catch (\Exception $e) {
show_error($e->getMessage());
}
}
Of course you don't have yo use show_error() and can instead return false, or set your own headers and your own message.
I am working on an ajax login for magento and I have run into a small issue when dealing with ssl.
The request page that I am using to display my login view is a non-secure page. From this page, I am using ajax to post to a secure url (https://client.devserver/customer/account/ajaxLoginPost/). The json response I get back is correct, however when I refresh the page the user is not logged in.
I have tested this function on a non-secure site and it works as intended. It seems to only break when I add in the next layer of SSL.
Any help with this is greatly appreciated.
Here is the code from my controller.
public function ajaxLoginPostAction()
{
if ($this->_getSession()->isLoggedIn()) {
$this->_redirect('*/*/');
return;
}
$session = $this->_getSession();
if ($this->getRequest()->isPost()) {
$login = $this->getRequest()->getPost('login');
if (!empty($login['username']) && !empty($login['password'])) {
try {
$session->login($login['username'], $login['password']);
if ($session->getCustomer()->getIsJustConfirmed()) {
$this->_welcomeCustomer($session->getCustomer(), true);
}
$messages = array("isAuthed" => true);
} catch (Mage_Core_Exception $e) {
switch ($e->getCode()) {
case Mage_Customer_Model_Customer::EXCEPTION_INVALID_EMAIL_OR_PASSWORD:
$message = $e->getMessage();
break;
default:
$message = $e->getMessage();
}
$messages = array("isAuthed" => false, "userName" => $login['username'],"error"=> $message);
} catch (Exception $e) {
// Mage::logException($e); // PA DSS violation: this exception log can disclose customer password
}
} else {
$messages = array("isAuthed" => false, "userName" => $login['username'],"error"=>'Login and password are required.');
}
}
//$this->_loginPostRedirect();
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($messages));
}
There are effectively two cookies (and hence two sessions), one for the "http" connection and one for the "https".
You can either forward to a secure page after performing the login - which negates the need for an AJAX form - or return the SID in the JSON response and find a way to set the non-secure cookie with that value.
A third option is to leave the entire site as secured, it's extra work & cost for the server so not all businesses are willing to take that sensible precaution.