catching GuzzleHttp \ Exception \ ConnectException and showing a custom message - php

I couldn't get a work around to catch this error and showing a custom message to user,
I tried to use web3js with laravel
https://github.com/IlyasDeckers/web3php
and when I tried to use this
$eth = new \IlyasDeckers\Web3PHP\Ethereum(env('WEB3_URL'), env('WEB3_PORT'));
try {
$eth = $eth->eth_getBalance('0x8fbb99e9e73cd62bb3adea5365ff0f9d90c9e532', $block='latest', $decode_hex=false);
}
catch(ConnectException $e) {
echo 'Message: ' .$e->getMessage();
exit;
}
I am getting the error which cannot be caught, can anyone help on this?
GuzzleHttp \ Exception \ ConnectException cURL error 7: Failed to
connect to 127.0.0.1 port 8545: Connection refused (see
http://curl.haxx.se/libcurl/c/libcurl-errors.html)

It sounds very much to me like you aren't running an Ethereum node. It's trying to connect to localhost on port 8545.
If you are running a node, check the port!
If you aren't running a node, either set one up, or find one that will allow you to connect (far less likely tbh).
UPDATE
I notice you are catching a ConnectException, the fully qualified classname being GuzzleHttp\Exception\ConnectException.
If you haven't imported the class name using a use statement, then you need to change your code to this:
catch (\GuzzleHttp\Exception\ConnectException) {
(note the leading backslash). However, this isn't the recommended way. It's better to import all your classes at the top of your script:
use GuzzleHttp\Exception\ConnectException;
That way, you can instantly see all classes used in the script, and you can refer to the class as just ConnectException throughout your code.

Related

PHPUnit Assertions project

I am working on a PHP project that requires validating a JSON request to a predefined schema, that is available in swagger. Now I have done my research and have found that the best project for this is SwaggerAssertions:
https://github.com/Maks3w/SwaggerAssertions
Within SwaggerAssertions/tests/PhpUnit/AssertsTraitTest.php, I would love to make use of the testAssertRequestBodyMatch method, where you do this:
self::assertRequestBodyMatch($request, $this->schemaManager, '/api/pets', 'post');
This assertion above does exactly what I need, but if I pass a invalid request it causes a fatal error. I want to trap this and handle the response back rather than the app quitting altogether.
How can I make use of this project, even though it looks like its all for PHPUnit? I am not too sure how one would make use of this project in normal PHP production code. Any help would be greatly appreciated.
Assertions throw exceptions if the condition is not met. If an exception is thrown, it will stop all following code from being executed until it's caught in a try catch block. Uncaught exceptions will cause a fatal error and the program will exit.
All you need to do to prevent your app from crashing, is handling the exception:
try {
self::assertRequestBodyMatch($request, $this->schemaManager, '/api/pets', 'post');
// Anything here will only be executed if the assertion passed
} catch (\Exception $e) {
// This will be executed if the assertion,
// or any other statement in the try block failed
// You should check the exception and handle it accordingly
if ($e instanceof \PHPUnit_Framework_ExpectationFailedException) {
// Do something if the assertion failed
}
// If you don't recognise the exception, re-throw it
throw $e;
}
Hope this helps.

Catching Exceptions from library using Laravel 5.2

Pretty new to laravel, so I'm not exactly sure how it handles errors and how best to catch them.
I'm using a 3rd party game server connection library that can query game servers in order to pull data such as players, current map etc..
This library is called Steam Condenser : https://github.com/koraktor/steam-condenser
I have imported this using composer in my project and all seems to be working fine, however I'm having trouble with catching exceptions that are thrown by the library.
One example is where the game server you are querying is offline.
Here is my code:
public function show($server_name)
{
try{
SteamSocket::setTimeout(3000);
$server = server::associatedServer($server_name);
$server_info = new SourceServer($server->server_ip);
$server_info->rconAuth($server->server_rcon);
$players = $server_info->getPlayers();
$total_players = count($players);
$more_info = $server_info->getServerInfo();
$maps = $server_info->rconExec('maps *');
preg_match_all("/(?<=fs\)).*?(?=\.bsp)/", $maps, $map_list);
}catch(SocketException $e){
dd("error");
}
return view('server', compact('server', 'server_info', 'total_players', 'players', 'more_info', 'map_list'));
}
If the server is offline, it will throw a SocketException, which I try to catch, however this never seems to happen. I then get the error page with the trace.
This causes a bit of a problem as I wish to simply tell the end user that the server is offline, however I cannot do this if I can't catch this error.
Is there something wrong with my try/catch? Does laravel handle catching errors in this way? Is this an issue with the 3rd party library?
A couple things:
Does the trace lead to the SocketException or to a different error? It's possible that a different error is being caught before the SocketException can be thrown.
Your catch statement is catching SocketException. Are you importing the full namespace at the top of your PHP file? use SteamCondenser\Exceptions\SocketException;
Also for debugging purposes, you could do an exception "catch all" and dump the type of exception:
try {
...
}catch(\Exception $e){
dd(get_class($e));
}
If you still get the stack trace after trying the above code, then an error is being thrown before the try/catch block starts.

How to handle Fatal error: cURL error 7: Failed to connect to xxxx port 443

I have a script that connects to a third party API. It is and should be running on a non-stop loop 24/7 (I use a sleep at the end before restarting the loop).
The problem is that sometimes the third party API gets ddosed or the connection simply drops with this error:
Fatal error: Uncaught exception
'GuzzleHttp\Ring\Exception\ConnectException' with message 'cURL error
7: Failed to connect to xxx.com port 443
Is there any way to "break" on this fatal error to ensure the code is restarted and proceed if the action can be made or must I manually restart each time I get this error?
From Michael's comment
it looks like you can just catch the GuzzleHttp\Ring\Exception\ConnectException exception
like this:
use GuzzleHttp\Ring\Exception\ConnectException;
try {
// the code which throws the error
} catch( ConnectException $ex ) {
switch ( $ex->getMessage() ) {
case '7': // to be verified
// handle your exception in the way you want,
// maybe with a graceful fallback
break;
}
}
it appears guzzle's ConnectException extends some classes and ultimately extends php's Exception so you can safely use the getCode() method, allowing you to catch an identifier on which you can react accordingly to your needs.
catch ConnectionException as sample code below:
use Illuminate\Http\Client\ConnectionException;
...
try {
Http::get('<your url>');
}
catch (ConnectionException $e) {
// Do something with $e for example Log::debug($e->getMessage());
}

swiftmailer Swift_TransportException gets uncaught by try-catch block

For a project (which is about estate properties) i have included a contact form where a visitor can contact an estate broker if the visitor is interested to buy/hire an estate property.
I am using Symfony2 and its library. For the contact mail, i am using the Swiftmailer library.
Well, i have the next code which handles the form submit. there, I create a mail object to be able to send mails. It works, but i want to provide a error resolving service if there are problems with the smtp host from sender/receiver.
Here is the code,
$data = $contactForm->getData();
try {
// create body text
$body = $app['twig']->render('mailTemplate.twig', array('data' => $data, 'immoid' => $immoID));
// set mail
$mail = \Swift_Message::newInstance()
->setSubject('Contact reaction on your immo offer.')
->setFrom($app['swiftconfig']['sender'])
->setTo($contactinfo['contactmail'])
->setBody($body, 'text/html');
// send mail
$app['mailer']->send($mail);
// redirect if successfull
$app->redirect($app['url_generator']->generate('immoDetail', array('immoID' => $immoID)));
}
catch (Swift_TransportException $STe) {
// logging error
$string = date("Y-m-d H:i:s") . ' - ' . $STe->getMessage() . PHP_EOL;
file_put_contents("errorlog.txt", $string, FILE_APPEND);
// send error note to user
$errorMsg = "the mail service has encountered a problem. Please retry later or contact the site admin.";
}
catch (Exception $e) {
// logging error
$string = date("Y-m-d H:i:s") . ' - GENERAL ERROR - ' . $e->getMessage() . PHP_EOL;
file_put_contents("errorlog.txt", $string, FILE_APPEND);
// redirect to error page
$app->abort(500, "Oops, something went seriously wrong. Please retry later !");
}
($app['swiftconfig']['sender'] = mailaddress from host / $contactinfo['contactmail'] = mailaddress from site visitor (submitted in contact form))
Now, when the smtp host doesn't work, Swiftmailer DOES send an exception, but the try-catch block ISN'T catching it. The function is just being continued.
Even the root try-catch block (in app.php) isn't catching it too. As a result of this, you see a large PHP error on the webpage, which shouldn't happen. The message from it is described here below,
SCREAM: Error suppression ignored for
---
Fatal error: Uncaught exception 'Swift_TransportException' with message ' in C:\...\vendor\swiftmailer\swiftmailer\lib\classes\Swift\Transport\StreamBuffer.php on line 266
---
Swift_TransportException: Connection could not be established with host <output omitted>
Does anyone know why the try catch block isn't catching the custom exception ? I have investigated the class files and the progress, but i don't see any unusual activity.
I hope that someone can come with a solution to this because PHP errors shouldn't appear on site pages.
remove from your config.yml
spool: { type: memory }
Then you will be to add try catch like this
try{
$mailer = $this->getMailer();
$response = $this->getMailer()->send($message);
}catch(\Swift_TransportException $e){
$response = $e->getMessage() ;
}
Try to put a backslash infront of Exception.
catch(\Exception $e)
A \ (backslash) before the beginning of a class name represents the Global Namespace.
Using a backslash will ensure that the Exception is called within the global namespace.
When you do $app['mailer']->send($mail); the email message is not being sent at that point if you have spooling turned on. See http://symfony.com/doc/current/cookbook/email/spool.html
If you have the default setting of spool: { type: memory }, the \Swift_TransportException will be thrown during the kernel termination phase, after you controller has exited.
One way around this is to turn off the spooling (but then your users might have to wait while the email is sent), or you can make your own eventlistener to handle the exception. http://symfony.com/doc/current/cookbook/service_container/event_listener.html
I ran into this problem in Laravel 4.2 when I added a SwiftMailerHandler to Monolog so it would email to me anything logged at a certain level or above. There was no way for me to catch the exception in the handler and it was thrown back to the browser. I solved it by subclassing SwiftMailerHandler:
<?php
/*******************************************************************************
* $Id: LogMailer.php 12152 2015-09-15 00:42:38Z sthames $ */
/**
* Subclass of Monolog SwiftMailerHandler that will catch exceptions SwiftMailer
* throws during the send. These exceptions are logged at the critical level.
* Without this, such exceptions are reported back to the browswer.
*******************************************************************************/
class LogMailer extends \Monolog\Handler\SwiftMailerHandler
{
/** Flag set when logging an exception during send. */
protected $dont_mail = false;
/** Overloads sender to catch and log errors during the send. */
protected function send($content, array $records)
{
try
{
if (!$this->dont_mail)
parent::send($content, $records);
}
catch(\Exception $e)
{
$this->dont_mail = true;
Log::critical($e->getMessage());
$this->dont_mail = false;
}
}
}
This handler catches the SwiftMailer exception and logs it at the critical level so it's not lost. I don't get an email about it but at least it's in the log.
I was surprised to find SwiftMailerHandler offered no way to inject an exception handler into the send method but fortunately the code is written well enough to make this solution pretty simple.
Works great and has given me no trouble so far.
Sure you have the latest version of swiftmailer? Line 226 of StreamBuffer.php doesn't throw any exception. This version from 2 years ago does throw the exception on that specific line.
I'd try running the latest version before diving into the issue more deeply.
SCREAM is a setting of XDebug that allows to see errors that are normally caught or suppressed. (Using #, for example.) Search for
xdebug.scream = 1
in your php.ini and set this to 0.
you can try below code for custom error:
public function render($request, Exception $exception)
{
if ($exception instanceof \Swift_TransportException) {
return response()->view('errors.404');
}
return parent::render($request, $exception);
}

Catch database exception in Kohana

I'm using Kohana 2. I would like to catch a database exception to prevent an error page when no connection to the server can be established.
The error displayed is
system/libraries/drivers/Database/Mysql.php [61]:
mysql_connect() [function.mysql-connect]: Lost connection to MySQL server at
'reading initial communication packet', system error: 110
The database server is not reachable at all at this point.
I'm doing this from a model. I tried both
public function __construct()
{
// load database library into $this->db
try
{
parent::__construct();
}
catch (Exception $e)
{
die('Database error occured');
}
}
as well as
try
{
$hoststatus = $this->db->query('SELECT x FROM y WHERE z;');
}
catch (Exception $e)
{
die('Database error occured');
}
...but none of them seemed to work. It seems as if no exception gets passed on from the main model. Is there another way to catch the database error and use my own error handling?
Kohana 2 does not convert errors into exceptions. You will either need to attach your own error handler, or use error_reporting() to turn off the error (temporarily) then do some kind of handling yourself.
You can catch the exception, but you are probably trying to catch it in the wrong place. The problem with trying to catch that low-level of an exception is that it can be spawned from many different sources.
For example, if you use the database driver for your sessions that exception will be thrown from instantiation of the database driver in the session library (which is instantiated in a call to session which will probably happen before you instantiate any models).
Catching that exception can happen from the model, but it is more likely to happen from another source - in which case you would probably have to extend a few libraries, or be sure you are wrapping a base model parent::__construct call and the session library in a try-catch block.
(I would personally extend the Model library to do that instead of putting it in a base model)
Hope that helps.
I don't know Kohana, but a try .. catch block will not catch normal errors, only Exceptions. Are you sure Kohana throws Exceptions where you expect to receive Exceptions?
Edit based on you comments:
Well, first of all, in a production environment (meaning your live application) you should always disable the displaying of PHP errors to the screen. Displaying of these errors to the screen should only be done in a development environment to inform you, the developer. Visitors of your live application however have no business in knowing/reading PHP errors, as it might disclose sensitive information about your environment. You should however log the errors to a log file.
Furthermore, I just took a quick peek at Kohana, and indeed see that here and there Exceptions are thrown, but it doesn't seem to do this in a consistent manner.
If you want php errors to be treated as Exceptions have a look example #1 in this documentation.

Categories