Skip to content

Commit d94f990

Browse files
authored
Merge pull request #5 from reactphp-parallel/support-an-array-of-middleware
Support an array of middleware
2 parents 5858a46 + 7bc3663 commit d94f990

File tree

8 files changed

+87
-17
lines changed

8 files changed

+87
-17
lines changed

src/Next.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ReactParallel\Psr15Adapter;
6+
7+
use Psr\Http\Message\ResponseInterface;
8+
use Psr\Http\Message\ServerRequestInterface;
9+
use Psr\Http\Server\MiddlewareInterface;
10+
use Psr\Http\Server\RequestHandlerInterface;
11+
12+
final class Next implements RequestHandlerInterface
13+
{
14+
private MiddlewareInterface $middleware;
15+
private RequestHandlerInterface $next;
16+
17+
public function __construct(MiddlewareInterface $middleware, RequestHandlerInterface $next)
18+
{
19+
$this->middleware = $middleware;
20+
$this->next = $next;
21+
}
22+
23+
public function handle(ServerRequestInterface $request): ResponseInterface
24+
{
25+
return $this->middleware->process($request, $this->next);
26+
}
27+
}

src/ReactMiddleware.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,19 @@ final class ReactMiddleware
2626
private WorkerPool $workerPool;
2727

2828
public function __construct(
29+
LoopInterface $loop,
30+
EventLoopBridge $eventLoopBridge,
2931
Factory $streamFactory,
3032
LowLevelPoolInterface $pool,
31-
MiddlewareInterface $middleware,
32-
LoopInterface $loop,
33-
EventLoopBridge $eventLoopBridge
33+
MiddlewareInterface ...$middleware
3434
) {
3535
$this->streamFactory = $streamFactory;
3636
$this->workerPool = new WorkerPool(
3737
$loop,
3838
$eventLoopBridge,
3939
$pool,
4040
new WorkerFactory(
41-
$middleware
41+
...$middleware
4242
),
4343
(int) '13'
4444
);

src/Worker.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
use ReactParallel\Pool\Worker\Work;
99
use ReactParallel\Pool\Worker\Work\Worker as WorkerContract;
1010

11+
use function array_reverse;
1112
use function assert;
1213

1314
final class Worker implements WorkerContract
1415
{
15-
private MiddlewareInterface $middleware;
16+
/** @var MiddlewareInterface[] */
17+
private array $middleware;
1618

17-
public function __construct(MiddlewareInterface $middleware)
19+
public function __construct(MiddlewareInterface ...$middleware)
1820
{
1921
$this->middleware = $middleware;
2022
}
@@ -27,6 +29,11 @@ public function perform(Work $workWrapper): Response
2729
$input = $work->input();
2830
$output = $work->output();
2931

30-
return new Response($this->middleware->process($request, new Psr15RequestHandlerAdapter($input, $output)));
32+
$requestHandler = new Psr15RequestHandlerAdapter($input, $output);
33+
foreach (array_reverse($this->middleware) as $middleware) {
34+
$requestHandler = new Next($middleware, $requestHandler);
35+
}
36+
37+
return new Response($requestHandler->handle($request));
3138
}
3239
}

src/WorkerFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ final class WorkerFactory implements WorkerFactoryContract
1515
{
1616
private string $middleware;
1717

18-
public function __construct(MiddlewareInterface $middleware)
18+
public function __construct(MiddlewareInterface ...$middleware)
1919
{
2020
$this->middleware = serialize($middleware);
2121
}
2222

2323
public function construct(): WorkerContract
2424
{
25-
return new Worker(unserialize($this->middleware));
25+
return new Worker(...unserialize($this->middleware));
2626
}
2727
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ReactParallel\Tests\Psr15Adapter;
6+
7+
use Psr\Http\Message\ResponseInterface;
8+
use Psr\Http\Message\ServerRequestInterface;
9+
use Psr\Http\Server\MiddlewareInterface;
10+
use Psr\Http\Server\RequestHandlerInterface;
11+
12+
use function Safe\sleep;
13+
14+
/**
15+
* @internal
16+
*/
17+
final class AnotherPsr15MiddlewareStub implements MiddlewareInterface
18+
{
19+
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
20+
{
21+
sleep(1);
22+
23+
return $handler->handle($request)->withAddedHeader('__CLASS__', self::class);
24+
}
25+
}

tests/ReactMiddlewareTest.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
use function assert;
2222
use function bin2hex;
23+
use function implode;
2324
use function iterator_to_array;
2425
use function random_bytes;
2526
use function React\Promise\resolve;
@@ -39,7 +40,8 @@ public function handle(): void
3940
$eventLoopBridge = new EventLoopBridge($loop);
4041
$pool = new Infinite($loop, $eventLoopBridge, 10);
4142
$stub = new Psr15MiddlewareStub();
42-
$middleware = new ReactMiddleware(new StreamFactory($eventLoopBridge), $pool, $stub, $loop, $eventLoopBridge);
43+
$anotherStub = new AnotherPsr15MiddlewareStub();
44+
$middleware = new ReactMiddleware($loop, $eventLoopBridge, new StreamFactory($eventLoopBridge), $pool, $stub, $stub, $anotherStub);
4345
$request = new ServerRequest('GET', 'https://example.com/');
4446
$request = $request->withAttribute('body', $rnd);
4547

@@ -66,7 +68,7 @@ static function (ServerRequestInterface $request): PromiseInterface {
6668
Info::SIZE => 1,
6769
], iterator_to_array($pool->info()));
6870

69-
$response = $this->await($promise, $loop, 3.3);
71+
$response = $this->await($promise, $loop, 9.9);
7072
assert($response instanceof ResponseInterface);
7173

7274
self::assertSame([
@@ -79,7 +81,10 @@ static function (ServerRequestInterface $request): PromiseInterface {
7981

8082
self::assertSame(666, $response->getStatusCode());
8183
self::assertSame($rnd, $response->getBody()->getContents());
82-
self::assertSame(Psr15MiddlewareStub::class, $response->getHeaderLine('__CLASS__'));
84+
self::assertSame(
85+
implode(', ', [AnotherPsr15MiddlewareStub::class, Psr15MiddlewareStub::class, Psr15MiddlewareStub::class]),
86+
$response->getHeaderLine('__CLASS__')
87+
);
8388

8489
$middleware->__destruct();
8590

tests/ResponseMiddlewareStub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ final class ResponseMiddlewareStub implements MiddlewareInterface
1717
{
1818
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
1919
{
20-
return new Response();
20+
return (new Response())->withAddedHeader('__CLASS__', self::class);
2121
}
2222
}

tests/WorkerTest.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use WyriHaximus\AsyncTestUtilities\AsyncTestCase;
1414

1515
use function assert;
16+
use function implode;
1617

1718
/**
1819
* @internal
@@ -24,11 +25,16 @@ final class WorkerTest extends AsyncTestCase
2425
*/
2526
public function handle(): void
2627
{
27-
$channel = new Channel(Channel::Infinite);
28-
$request = $this->prophesize(ServerRequestInterface::class)->reveal();
29-
$stub = new ResponseMiddlewareStub();
30-
$response = (new WorkerFactory($stub))->construct()->perform(new Work(new Request($request, $channel, $channel)));
28+
$channel = new Channel(Channel::Infinite);
29+
$request = $this->prophesize(ServerRequestInterface::class)->reveal();
30+
$responseMiddlewareStub = new ResponseMiddlewareStub();
31+
$stub = new Psr15MiddlewareStub();
32+
$response = (new WorkerFactory($stub, $stub, $responseMiddlewareStub))->construct()->perform(new Work(new Request($request, $channel, $channel)));
3133
assert($response instanceof Response);
3234
self::assertSame(200, $response->result()->getStatusCode());
35+
self::assertSame(
36+
implode(', ', [ResponseMiddlewareStub::class, Psr15MiddlewareStub::class, Psr15MiddlewareStub::class]),
37+
$response->result()->getHeaderLine('__CLASS__')
38+
);
3339
}
3440
}

0 commit comments

Comments
 (0)