Skip to content

Commit 206578a

Browse files
tareqasnicolas-grekas
authored andcommitted
Clean up API error handling with concise user messages
1 parent 9aad744 commit 206578a

File tree

4 files changed

+82
-8
lines changed

4 files changed

+82
-8
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace SensioLabs\Insight\Cli\EventListener;
4+
5+
use SensioLabs\Insight\Sdk\Exception\ApiClientException;
6+
use SensioLabs\Insight\Sdk\Exception\ApiParserException;
7+
use SensioLabs\Insight\Sdk\Exception\ApiServerException;
8+
use Symfony\Component\Console\ConsoleEvents;
9+
use Symfony\Component\Console\Event\ConsoleErrorEvent;
10+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
11+
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
12+
13+
class ApiErrorListener implements EventSubscriberInterface
14+
{
15+
public static function getSubscribedEvents(): array
16+
{
17+
return [
18+
ConsoleEvents::ERROR => ['onConsoleError', 256],
19+
];
20+
}
21+
22+
public function onConsoleError(ConsoleErrorEvent $event): void
23+
{
24+
$output = $event->getOutput();
25+
$error = $event->getError();
26+
27+
if ($error instanceof ApiClientException) {
28+
$this->showClientError($error, $output);
29+
} elseif ($error instanceof ApiServerException) {
30+
$output->writeln('<error>Server temporarily unavailable. Please try again in a few minutes.</error>');
31+
} elseif ($error instanceof ApiParserException) {
32+
$output->writeln('<error>Unable to process server response. Please try again later.</error>');
33+
} elseif ($error instanceof TransportExceptionInterface) {
34+
$output->writeln('<error>Network connection failed. Check your internet connection.</error>');
35+
} else {
36+
$output->writeln('<error>Something went wrong. Please try again, or run with -v for more details.</error>');
37+
}
38+
39+
if ($output->isVerbose()) {
40+
throw $error;
41+
}
42+
43+
$event->setExitCode(0);
44+
}
45+
46+
private function showClientError(ApiClientException $e, $output): void
47+
{
48+
$message = $e->getMessage();
49+
if (false !== strpos($message, '401') || false !== strpos($message, 'Unauthorized')) {
50+
$output->writeln('<error>Invalid API credentials. Run "php insight.phar configure" to set up your token.</error>');
51+
} elseif (false !== strpos($message, '404') || false !== strpos($message, 'Not Found')) {
52+
$output->writeln('<error>Project not found. Check the project UUID and try again.</error>');
53+
} elseif (false !== strpos($message, '403') || false !== strpos($message, 'Forbidden')) {
54+
$output->writeln('<error>Access denied. You don\'t have permission for this project.</error>');
55+
} else {
56+
$output->writeln('<error>Request failed. Please check your input and try again.</error>');
57+
}
58+
}
59+
}

Sdk/Api.php

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,12 +289,22 @@ private function processClientError(HttpExceptionInterface $e)
289289

290290
private function logException(ExceptionInterface $e)
291291
{
292-
$message = sprintf("Exception: Class: \"%s\", Message: \"%s\", Response:\n%s",
293-
\get_class($e),
294-
$e->getMessage(),
295-
$e->getResponse()->getInfo('debug')
296-
);
292+
if (!$this->logger) {
293+
return;
294+
}
295+
296+
$parts = [
297+
sprintf('Exception: Class: "%s"', \get_class($e)),
298+
sprintf('Message: "%s"', $e->getMessage()),
299+
];
300+
301+
if ($e instanceof HttpExceptionInterface) {
302+
$debug = $e->getResponse()->getInfo('debug');
303+
if ($debug) {
304+
$parts[] = "Response:\n".$debug;
305+
}
306+
}
297307

298-
$this->logger && $this->logger->error($message, ['exception' => $e]);
308+
$this->logger->error(implode(', ', $parts), ['exception' => $e]);
299309
}
300310
}

bin/insight

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ if (file_exists($a = __DIR__.'/../../../autoload.php')) {
1818
}
1919

2020
use SensioLabs\Insight\Cli\Application;
21+
use Symfony\Component\EventDispatcher\EventDispatcher;
22+
use SensioLabs\Insight\Cli\EventListener\ApiErrorListener;
2123

2224
$application = new Application();
23-
25+
$dispatcher = new EventDispatcher();
26+
$dispatcher->addSubscriber(new ApiErrorListener());
27+
$application->setDispatcher($dispatcher);
2428
$application->run();

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"psr/log": "^1.0",
1111
"symfony/http-client": "^5.4|^6.4|^7.0",
1212
"symfony/console": "^5.4|^6.4|^7.0",
13-
"symfony/expression-language": "^5.4|^6.4|^7.0"
13+
"symfony/expression-language": "^5.4|^6.4|^7.0",
14+
"symfony/event-dispatcher": "^5.4|^6.4|^7.0"
1415
},
1516
"require-dev": {
1617
"monolog/monolog": "^1.4",

0 commit comments

Comments
 (0)