diff --git a/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php b/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php index 7d46fe9c2e5..94bd24e3387 100644 --- a/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php +++ b/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php @@ -84,6 +84,17 @@ public function handleRequest(RequestInterface $request, callable $next, callabl } } + if (502 == $response->getStatusCode() && isset($content['errors']) && is_array($content['errors'])) { + $errors = []; + foreach ($content['errors'] as $error) { + if (isset($error['message'])) { + $errors[] = $error['message']; + } + } + + throw new RuntimeException(implode(', ', $errors), 502); + } + throw new RuntimeException(isset($content['message']) ? $content['message'] : $content, $response->getStatusCode()); }); } diff --git a/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php new file mode 100644 index 00000000000..fd83e88c2f4 --- /dev/null +++ b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php @@ -0,0 +1,149 @@ + + */ +class GithubExceptionThrowerTest extends TestCase +{ + /** + * @param ResponseInterface $response + * @param ExceptionInterface|\Exception|null $exception + * @dataProvider responseProvider + */ + public function testHandleRequest(ResponseInterface $response, ExceptionInterface $exception = null) + { + /** @var RequestInterface $request */ + $request = $this->getMockForAbstractClass(RequestInterface::class); + + $promise = $this->getMockBuilder(FulfilledPromise::class)->disableOriginalConstructor()->getMock(); + $promise->expects($this->once()) + ->method('then') + ->willReturnCallback(function ($callback) use ($response) { + return $callback($response); + }); + + $plugin = new GithubExceptionThrower(); + + if ($exception) { + $this->expectException(get_class($exception)); + $this->expectExceptionCode($exception->getCode()); + $this->expectExceptionMessage($exception->getMessage()); + } + + $plugin->handleRequest( + $request, + function (RequestInterface $request) use ($promise) { + return $promise; + }, + function (RequestInterface $request) use ($promise) { + return $promise; + } + ); + } + + /** + * @return array + */ + public static function responseProvider() + { + return [ + '200 Response' => [ + 'response' => new Response(), + 'exception' => null, + ], + 'Rate Limit Exceeded' => [ + 'response' => new Response( + 429, + [ + 'Content-Type' => 'application/json', + 'X-RateLimit-Remaining' => 0, + 'X-RateLimit-Limit' => 5000, + ], + '' + ), + 'exception' => new \Github\Exception\ApiLimitExceedException(5000), + ], + 'Two Factor Authentication Required' => [ + 'response' => new Response( + 401, + [ + 'Content-Type' => 'application/json', + 'X-GitHub-OTP' => 'required; :2fa-type', + ], + '' + ), + 'exception' => new \Github\Exception\TwoFactorAuthenticationRequiredException('2fa-type'), + ], + '400 Bad Request' => [ + 'response' => new Response( + 400, + [ + 'Content-Type' => 'application/json', + ], + json_encode( + [ + 'message' => 'Bad Request', + ] + ) + ), + 'exception' => new \Github\Exception\ErrorException('Bad Request', 400), + ], + '422 Unprocessable Entity' => [ + 'response' => new Response( + 422, + [ + 'Content-Type' => 'application/json', + ], + json_encode( + [ + 'message' => 'Bad Request', + 'errors' => [ + [ + 'code' => 'missing', + 'field' => 'field', + 'value' => 'value', + 'resource' => 'resource', + ], + ], + ] + ) + ), + 'exception' => new \Github\Exception\ErrorException('Validation Failed: The field value does not exist, for resource "resource"', 422), + ], + '502 Response' => [ + 'response' => new Response( + 502, + [ + 'Content-Type' => 'application/json', + ], + json_encode( + [ + 'errors' => [ + ['message' => 'Something went wrong with executing your query'], + ], + ] + ) + ), + 'exception' => new \Github\Exception\RuntimeException('Something went wrong with executing your query', 502), + ], + 'Default handling' => [ + 'response' => new Response( + 555, + [], + 'Error message' + ), + 'exception' => new \Github\Exception\RuntimeException('Error message', 555), + ], + ]; + } +}