Laravel Remote/SSH catch SSH2 Exception - php

When im attempting to deploy things using laravel 4.1's SSH/Remote classes occasionally i get this exception
[2014-01-03 18:26:21] production.ERROR: exception 'ErrorException' with message 'Connection closed by server' in /home/{user}/{location}/deploy/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php:918
I was wondering if there is a way to detect if it has failed to connect in order to attempt the connection again and or multiple times?
Any ideas?

Laravel uses phpseclib for its SSH library. On connection failure, phpseclib executes user_error('Connection closed by server'); (see Net/SSH2.php, line ~911). Laravel has a global error handler that picks this up, and logs it (as you saw in your question).
Unfortunately, phpseclib triggers errors, instead of throwing exceptions. If they were exceptions, you could add a new condition to Laravel's error handling:
App::error(function(Exception $exception){
Log::error($exception);
if($exception instanceof PHPSecLibException){
// Let's handle this
}
});
This definitely would be the "right way" to do it, but these aren't true exceptions (they're generic Laravel exceptions that are generated on your behalf when errors are triggered).
Luckily, Laravel translates errors into exceptions on your behalf. See src/Illuminate/Exception/Handler.php (lines ~129-135). So we could just add a conditional based on the info you do have:
App::error(function(Exception $exception){
Log::error($exception);
if(($exception->getMessage() == "Connection closed by server") &&
($exception->getFile() == "/home/{user}/{location}/deploy/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php")){
// Let's handle this
}
});
Take a look at the Exception methods available.

Related

Laravel Turn Off Exception Handler [duplicate]

This question already has answers here:
Disable Laravel's built-in error handling methods
(7 answers)
Closed 1 year ago.
In Laravel, whenever there error, even minor NOTICES, WARNINGS and DEPRECATED erros, I got the full debug info which kills the application. In my App.config I've turned debug => false and I get the message of 'Whoops, looks like something went wrong.'
How can I turn off all error handling but Laravel to just get normal PHP errors that do not interrupt the entire flow of application?
If you don't want to interrupt your workflow for certain PHP error types, you will need to disable the error handler registered by Laravel for those errors.
Laravel registers its error handling in Illuminate/Foundation/Bootstrap/HandleExceptions.php. This bootstrapper is one of several that is called when your Http kernel handles a request.
While there are a couple ways to do what you want to do, I think the easiest is to handle the event that is fired after this bootstrapper is called. In the event handler, you can reset the error handler for the errors you don't want Laravel to process.
In your bootstrap/app.php file, add the following line right before $app is returned:
$app->afterBootstrapping(
'Illuminate\Foundation\Bootstrap\HandleExceptions',
function ($app) {
set_error_handler(function ($level, $message, $file = '', $line = 0, $context = []) {
// Check if this error level is handled by error reporting
if (error_reporting() & $level) {
// Return false for any error levels that should
// be handled by the built in PHP error handler.
if ($level & (E_WARNING | E_NOTICE | E_DEPRECATED)) {
return false;
}
// Throw an exception to be handled by Laravel for all other errors.
throw new ErrorException($message, 0, $level, $file, $line);
}
});
}
);
The App\Exceptions\Handler.php file is built just for this.
In the public function render() method, you can catch applications and perform certain redirects/page views if you so choose:
For instance, you can capture HttpException's in your application and then return an error page if you wished:
public function render($request, Exception $e)
{
//other stuff
if ($e instanceof HttpException) {
return view('errors.general')->withErrors([
'message' => 'The application encountered an error!'
]);
}
return parent::render($request, $exception);
}
That up-voted answer is the opposite of what he asked.
As far as I can tell, there isn't a way to separate error reporting and laravel taking over rendering of the screen. I've been looking through the Laravel 5 code and haven't found a way to split them apart using their setup yet.
You could write your own library to totally take over all error handling and remove all of laravels internal tracking, but then you'd have to make sure to pass it back to laravel in the cases where you need the orig page error handling. Easiest way would be find a 3rd part error handler vendor then modify it to take over all error handlers and not block rendering.

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.

Exceptions - for user notifications or error logging?

I'm trying to figure out what exceptions should be used for; logging application errors, or displaying user errors, and if both, how should I distinguish between and handle a user error (e.g. failed login) and an application error (e.g. a failure to connect to the database) with exceptions.
For example, let's say a user attempts to login, but fails (user error):
if(!$user->login($_POST)) {
//$user->login() throws an Exception, throw new Exception("failed login"), on fail.
catch(Exception $e) {
print $e->getMessage();
}
}
Or perhaps a database error occurs (error logging):
public function query($query) {
$this->resource = mysql_query($query) or throw new Exception("Database error:" . mysql_error());
}
Which of the above two examples would be an appropriate use case, if either?
Exceptions are for signalling exceptional behaviour on part of your program. During normal operation, your program should not usually throw exceptions at all. Something like a failed login is a normal result of your login mechanism, not an exception.
[A failed login may be an exception on the user's end (if the user had reason to expect the login to work unconditionally)!]
Typical exceptional situations are running out of memory, running out of disk space, an error in the database connection, or an error during reading or writing a file. All those are things that you would normally expect to work, so an error there is an exceptional condition.
See my previous answer for more details.

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