Exception handling in amazon S3 SDK for PHP - php

I recently migrated from age old amazon AWS SDK (v1.6.2) for PHP to the latest one. One thing I completely missed was Exception handling.
My first code.
$result = $this->S3Client->putObject($options);
if (!empty($result)) {
return !0;
}
But if upload fails, then it will throw an exception which will crash my PHP. So, I added exception handling next.
try {
$result = $this->S3Client->putObject($options);
return !0;
} catch(Exception $e) {
log_message($e->message);
return !1;
}
However, it seems that $e->message is protected.
Question: How can I get the error so that I can root cause what happened with the upload, once I move to production environment?

Try using:
log_message($e->getMessage());
More info here and here.

Related

How to catch an error thrown by a third party library in PHP

I'm using the phpWhois package in my Laravel application for performing whois lookup.
It's working fine except that for some websites that I enter, this error always occurs:
'ErrorException in whois.gtld.godaddy.php line 50: Undefined index: owner'
I googled it and found that this problem already has an open issue on Github and also an existing pull request.
I don't want to copy and paste the suggested fix in the source code because it means I have to do it in every time I do composer install.
So I decided to catch the error instead but I don't know how.
I found a somewhat similar question here and tried the accepted solution but it is still throwing the exception.
Here's the existing code that I tried:
$whois = new \Whois();
try {
$result = $whois->lookup($data['name']);
} catch (Exception $e) {
return response()->json(['error' => $e]);
}
I would appreciate any comment/help.
Thanks for your time.
If you want to catch an exception,You follow below mentioned programming style.
try {
$whois = new \Whois();
$result = $whois->lookup($data['name']);
} catch (\Exception $e) {
\var_dump($e->getMessage());
}
This above mentioned method work in almost all PHP frameworks.

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.

Console Commands with ErrorException exit my script instead of continuing after an error

I just upgraded from 4.2 to 5.0. I got all of my commands working, but I noticed in one script I see an error (an expected error) which reports ErrorException. The problem is, it breaks my script from continuing instead of moving on the the next step in a foreach loop. The same error with the same script on 4.2 will report the error and continue.
4.2: Cannot connect to xyz.IP Error 60. Operation timed out
5.0: [ErrorException]
Cannot connect to xyz.IP Error 60. Operation timed out
For more context: I'm using the script to SSH into a couple of servers and run a Ping command. I'm using Phpseclib 1.0. I've tested phpseclib on my old 4.2 build and it works fine. 5.0 is where the problem started occuring.
Does anyone know how I can make the script continue to run after an ErrorException?
foreach ($query as $key => $value) {
$ssh = new Net_SSH2($value->origin_ip);
$key = new Crypt_RSA();
$key->loadKey(decryptIt($value->password));
if (!$ssh->login($value->username, $key)) {
exit('Login Failed');
}
$this->info(' Running Ping');
//$ssh->setTimeout(1);
if ($ssh->read('/.*#.*[$|#]/', NET_SSH2_READ_REGEX)) {
//echo "reading";
//$this->info(' Running Ping');
//$ssh->setTimeout(4);
$statusOutput=$ssh->exec("ping -c 1 -W 1 ".$value->destination_ip." >/dev/null 2>&1; echo $? ");
} else {
//echo "not reading";
$this->error("Unable to Read Ping");
}
}
To work with exceptions inline within a script, use a try...catch block:
try {
$value = someFunctionThatMayCauseAnException();
} catch (Exception $e) {
$errorMessage = $e->getMessage();
}
For more information, see the PHP manual entry for Exceptions
"Uncaught" exceptions will halt your script. Sometimes, that is the desired effect. For example, the SSH library you're using does not catch the exceptions that occur within the methods, they are allowed to bubble out to the calling script. Maybe your calling script catches them, or maybe you let them keep bubbling to your global exception handler. There are a number of ways to work with exceptions, but the general rule of thumb is that you don't catch them unless you're going to do something with it, like show an error message.
Your script would continue in the previous version because the error was, most likely, emitted as a warning or notice and returning false to indicate failure. With the newer PHP version, the library began emitting exceptions instead, at once indicating failure AND providing an exception object with details about the failure.
This means you'll have to restructure the logic within your loop instead of directly calling the function in a conditional if. You didn't specify which line is emitting the exception in your example, but for instance, this is one way that you could restructure to work with exceptions:
$errorMessage = false;
try {
$ssh->login($value->username, $key); // this code is attempted
} catch (Exception $e) {
// if an exception is emitted
// in the try block above, this block
// is reached. Otherwise, it is skipped
$errorMessage = $e->getMessage();
}
// $errorMessage can only be other than false from the exception catch block above
if ($errorMessage !== false) {
exit($errorMessage);
}
Solved it. I had a try catch which I modified.
Make sure the catch has a backwards slash like this:
try {
//code here
} catch (\Exception $e) {
print_r($e->getMessage());
}

Symfony SncRedis Bundle exception handling if redis not available

I am using redis as a cache to help with application performance regarding data that has a high cost of generation. Currently we only have one redis instance running and I have observed that if redis is not available - then 500 error is being returned.
Given that I am caching - I would rather continue processing if redis is down and render that page with the data omitted.
I have tested using a basic php try - catch block - but it I have not been able to trap the exception.
public function redisAction()
{
try {
$redis = $this->container->get('snc_redis.default');
$val = $redis->get('foo:bar');
} catch (Exception $e ) {
$response = new Response('Oops ');
return $response;
}
....
}
Is there any other approaches I can take - I am also investigating the sncredis bundle to see if it can be addressed there.
Given you did not include use Exception on top of your class you will need to add a leading backslash ... otherwise PHP will try to catch Your\Current\Namespace\Exception which doesn't exist.
catch (\Exception $e ) {
// ...
}
But I'm not sure if redis throws an exception if the requested key does not exist (actually I don't think so).
You could use the exists() method to check if the key exists instead.
if ($redis->exists("foo:bar")) {
return new Response('Oops');
}

Facebook PHP SDK throws uncatchable "GraphMethodException" error

I'm experiencing something eerily similar to this question about an uncatchable PHP error thrown by the Facebook PHP SDK except for the fact that I'm not using PHP namespaces at all. This other question is also close, but doesn't explain why the error is uncatchable. Further, in my case, I have a Facebook app that issues a Facebook Graph API call against an object that the current user has blocked. This is certainly awkward, but legal for the purposes of this particular app. That means I need to catch the error, not prevent the user from making the search in the first place.
The fatal error's output in my development environment looks like this:
Fatal error: Uncaught GraphMethodException: Unsupported get request. thrown in /path/to/apps/lib/facebook/src/base_facebook.php on line 1271
So, Facebook's Graph API correctly returns an error as a result of the API call, citing "Unsupported get request." However, the Facebook PHP SDK seems to throw this as an uncatchable error, and I don't know why.
I've tried code like the following catch blocks with no success:
try {
$response = $facebook->api("/$some_id_of_object_current_user_has_blocked");
} catch (FacebookApiException $e) {
// Why does this never get caught?
} catch (Exception $e) {
// Similarly, this also never gets caught!
} catch (GraphMethodException $e) {
// Still can't catch this exception, and I don't grok why. :(
}
For the sake of ridiculous completeness, I've also tried namespaces including things like this:
try {
$response = $facebook->api("/$some_id_of_object_current_user_has_blocked");
} catch (\FacebookApiException $e) {
} catch (\Exception $e) {
} catch (\FacebookApiException\GraphMethodException $e) {
} catch (\GraphMethodException $e) {
} catch (... $e) {
}
Further investigation lead me to try catching this in the base_facebook.php file itself, where it seems to get thrown, in the protected Facebook::_graph method. And sure enough, it is catchable there. The original code at about line 879 of base_facebook.php is:
if (is_array($result) && isset($result['error'])) {
$this->throwAPIException($result);
// #codeCoverageIgnoreStart
}
Wrapping this call to throwAPIException() with a try...catch block works:
if (is_array($result) && isset($result['error'])) {
try {
$this->throwAPIException($result);
// #codeCoverageIgnoreStart
} catch (Exception $e) {
// WORKS!
}
}
So if it works there, why can't I catch this exception from my own scripts? Am I missing something fundamental about the way PHP error handling works?
Alternatively, is there a way for a Facebook app to get a list of all the objects a Facebook user has blocked, such as other Facebook users a user has blocked? I'm familiar with Graph API enough to know that there's a way for an app to access a list of all users a page has blocked, but that's specifically not what I'm looking for.
Thanks for your time.
It's apparently uncatchable because it relates to the permissions your app uses.
In your case, it looks like you were trying to GET the same thing as me, which requires the permission: read_stream
It makes sense that they would make this sort of thing uncatchable - but you'd think the facebook devs could do something a little more friendly...
Adding the try/catch around $this->throwAPIException($result); works in suppressing the error message but I would recommend checking the inputs to your functions to ensure they exist and are valid.
For example, check to see if $SESSION['fb<your_app_id>_access_token'] exists and is not null before passing this to any functions. If this is not set or is null, none of the functions that rely on it will work and you can catch the potential issue before communicating with Facebook's servers, which speeds up your application by skipping a function you can determine ahead of time will fail, and resolve issues quicker by asking for corrections proactively instead of re-actively.
I also was seeing this error which apparently was caused by my app not having the appropriate permissions, as #rm-vanda stated. Because the app id does not have the permissions, a token is not returned which results in the error you are seeing.
Hope that helps!

Categories