Skip to content

Commit

Permalink
Exceptions plugin to throw exceptions based on Matej API response code
Browse files Browse the repository at this point in the history
  • Loading branch information
OndraM committed Nov 10, 2017
1 parent 89b38e8 commit 2efb101
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 1 deletion.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"php-http/message": "^1.0",
"php-http/client-implementation": "^1.0",
"php-http/discovery": "^1.0",
"fig/http-message-util": "^1.1"
"fig/http-message-util": "^1.1",
"php-http/client-common": "^1.6"
},
"require-dev": {
"php-http/guzzle6-adapter": "^1.1",
Expand Down
40 changes: 40 additions & 0 deletions src/Http/Plugin/ExceptionPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php declare(strict_types=1);

namespace Lmc\Matej\Http\Plugin;

use Fig\Http\Message\StatusCodeInterface;
use Http\Client\Common\Plugin;
use Http\Promise\Promise;
use Lmc\Matej\Exception\AuthorizationException;
use Lmc\Matej\Exception\RequestException;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

final class ExceptionPlugin implements Plugin
{
public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise
{
/** @var Promise $promise */
$promise = $next($request);

return $promise->then(function (ResponseInterface $response) use ($request) {
return $this->transformResponseToException($request, $response);
});
}

private function transformResponseToException(RequestInterface $request, ResponseInterface $response)
{
$responseCode = $response->getStatusCode();

if ($responseCode === StatusCodeInterface::STATUS_UNAUTHORIZED) {
throw AuthorizationException::createFromRequestAndResponse($request, $response);
}

if ($responseCode >= 400 && $responseCode < 600) {
// TODO: use more specific exceptions
throw new RequestException($response->getReasonPhrase(), $request, $response);
}

return $response;
}
}
77 changes: 77 additions & 0 deletions tests/Http/Plugin/ExceptionPluginTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php
declare(strict_types=1);

namespace Lmc\Matej\Http\Plugin;

use Fig\Http\Message\StatusCodeInterface;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use Http\Client\Promise\HttpFulfilledPromise;
use Lmc\Matej\Exception\AuthorizationException;
use Lmc\Matej\Exception\RequestException;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\RequestInterface;

class ExceptionPluginTest extends TestCase
{
/** @var callable */
protected $emptyFunction;

/** @before */
public function init(): void
{
$this->emptyFunction = function (): void {
};
}

/** @test */
public function shouldReturnResponseWhenNoError(): void
{
$request = new Request('GET', 'http://foo.com/endpoint');
$response = new Response(StatusCodeInterface::STATUS_OK);

$next = function (RequestInterface $receivedRequest) use ($request, $response) {
$this->assertSame($request, $receivedRequest);

return new HttpFulfilledPromise($response);
};

$plugin = new ExceptionPlugin();
$promise = $plugin->handleRequest($request, $next, $this->emptyFunction);
$this->assertInstanceOf(HttpFulfilledPromise::class, $promise);
}

/**
* @test
* @dataProvider provideErrorStatusCodes
*/
public function shouldThrowExceptionBasedOnStatusCode(int $statusCode, string $expectedExceptionClass): void
{
$request = new Request('GET', 'http://foo.com/endpoint');
$response = new Response($statusCode);

$next = function (RequestInterface $receivedRequest) use ($request, $response) {
$this->assertSame($request, $receivedRequest);

return new HttpFulfilledPromise($response);
};

$plugin = new ExceptionPlugin();

$this->expectException($expectedExceptionClass);
$plugin->handleRequest($request, $next, $this->emptyFunction);
}

/**
* @return array[]
*/
public function provideErrorStatusCodes(): array
{
return [
'HTTP 400' => [StatusCodeInterface::STATUS_BAD_REQUEST, RequestException::class],
'HTTP 401' => [StatusCodeInterface::STATUS_UNAUTHORIZED, AuthorizationException::class],
'HTTP 404' => [StatusCodeInterface::STATUS_NOT_FOUND, RequestException::class],
'HTTP 500' => [StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR, RequestException::class],
];
}
}

0 comments on commit 2efb101

Please sign in to comment.