Skip to content

Commit 891153d

Browse files
committed
Implemented HttpExceptionsMiddleware
1 parent d38188e commit 891153d

File tree

4 files changed

+158
-2
lines changed

4 files changed

+158
-2
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"require": {
1212
"php": "^7.0",
1313
"api-clients/middleware": "^2.0",
14+
"api-clients/psr7-http-status-exceptions": "dev-master",
1415
"clue/buzz-react": "^1.1"
1516
},
1617
"require-dev": {

composer.lock

Lines changed: 46 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/HttpExceptionsMiddleware.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Middleware\HttpExceptions;
4+
5+
use ApiClients\Foundation\Middleware\MiddlewareInterface;
6+
use ApiClients\Foundation\Middleware\PostTrait;
7+
use ApiClients\Foundation\Middleware\PreTrait;
8+
use ApiClients\Foundation\Middleware\Priority;
9+
use ApiClients\Tools\Psr7\HttpStatusExceptions\ExceptionFactory;
10+
use Clue\React\Buzz\Message\ResponseException;
11+
use React\Promise\CancellablePromiseInterface;
12+
use Throwable;
13+
use function React\Promise\reject;
14+
15+
final class HttpExceptionsMiddleware implements MiddlewareInterface
16+
{
17+
use PreTrait;
18+
use PostTrait;
19+
20+
/**
21+
* @return int
22+
*/
23+
public function priority(): int
24+
{
25+
return Priority::SECOND_LAST;
26+
}
27+
28+
/**
29+
* When $throwable is a ResponseException this method will turn it into a
30+
* HTTP status code specific exception.
31+
*
32+
* @param Throwable $throwable
33+
* @param array $options
34+
* @return CancellablePromiseInterface
35+
*/
36+
public function error(Throwable $throwable, array $options = []): CancellablePromiseInterface
37+
{
38+
if (!($throwable instanceof ResponseException)) {
39+
return reject($throwable);
40+
}
41+
42+
return reject(ExceptionFactory::create($throwable->getResponse(), $throwable));
43+
}
44+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Tests\Middleware\HttpExceptions;
4+
5+
use ApiClients\Foundation\Middleware\Priority;
6+
use ApiClients\Middleware\HttpExceptions\HttpExceptionsMiddleware;
7+
use ApiClients\Tools\Psr7\HttpStatusExceptions\ExceptionFactory;
8+
use ApiClients\Tools\TestUtilities\TestCase;
9+
use Clue\React\Buzz\Message\ResponseException;
10+
use Exception;
11+
use React\EventLoop\Factory;
12+
use RingCentral\Psr7\Response;
13+
use Throwable;
14+
use function Clue\React\Block\await;
15+
use function React\Promise\reject;
16+
17+
final class HttpExceptionsMiddlewareTest extends TestCase
18+
{
19+
/**
20+
* Ensure we run second last so the last can be logging or so that stores information.
21+
*/
22+
public function testPriority()
23+
{
24+
self::assertSame(
25+
Priority::SECOND_LAST,
26+
(new HttpExceptionsMiddleware())->priority()
27+
);
28+
}
29+
30+
public function provideThrowables()
31+
{
32+
yield [
33+
new Exception('foo.bar'),
34+
new Exception('foo.bar'),
35+
];
36+
37+
foreach (ExceptionFactory::STATUS_CODE_EXCEPTION_MAP as $code => $exception) {
38+
$response = new Response($code);
39+
$responseException = new ResponseException(
40+
new Response($code)
41+
);
42+
yield [
43+
$responseException,
44+
$exception::create($response, $responseException)
45+
];
46+
}
47+
}
48+
49+
/**
50+
* @dataProvider provideThrowables
51+
*/
52+
public function testException(Throwable $input, Throwable $output)
53+
{
54+
$result = null;
55+
56+
try {
57+
await(
58+
(new HttpExceptionsMiddleware())->error($input, []),
59+
Factory::create()
60+
);
61+
} catch (Throwable $result) {
62+
}
63+
64+
self::assertNotNull($result);
65+
self::assertEquals($output, $result);
66+
}
67+
}

0 commit comments

Comments
 (0)