Skip to content

Commit b8ac9d8

Browse files
committed
:octocat: PSR-15 middleware
1 parent 2df8c22 commit b8ac9d8

10 files changed

+553
-2
lines changed

composer.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"license": "MIT",
55
"type": "library",
66
"keywords": [
7-
"http", "message", "client", "factory", "psr-7", "psr-17", "psr-18"
7+
"http", "message", "client", "factory", "handler", "psr-7", "psr-15", "psr-17", "psr-18"
88
],
99
"minimum-stability": "stable",
1010
"authors": [
@@ -22,7 +22,9 @@
2222
"chillerlan/php-httpinterface": "2.0",
2323
"psr/http-client-implementation": "1.0",
2424
"psr/http-factory-implementation": "1.0",
25-
"psr/http-message-implementation": "1.0"
25+
"psr/http-message-implementation": "1.0",
26+
"psr/http-server-handler-implementation": "1.0",
27+
"psr/http-server-middleware-implementation": "1.0"
2628
},
2729
"require": {
2830
"php": "^7.2",
@@ -34,6 +36,8 @@
3436
"psr/http-client":"^1.0",
3537
"psr/http-message": "^1.0",
3638
"psr/http-factory":"^1.0",
39+
"psr/http-server-handler": "^1.0",
40+
"psr/http-server-middleware": "^1.0",
3741
"psr/log": "^1.0"
3842
},
3943
"require-dev": {

src/Psr15/EmptyResponseHandler.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
/**
3+
* Class EmptyResponseHandler
4+
*
5+
* @filesource EmptyResponseHandler.php
6+
* @created 09.03.2019
7+
* @package chillerlan\HTTP\Psr15
8+
* @author smiley <[email protected]>
9+
* @copyright 2019 smiley
10+
* @license MIT
11+
*/
12+
13+
namespace chillerlan\HTTP\Psr15;
14+
15+
use Psr\Http\Message\{ResponseFactoryInterface, ResponseInterface, ServerRequestInterface};
16+
use Psr\Http\Server\RequestHandlerInterface;
17+
18+
class EmptyResponseHandler implements RequestHandlerInterface{
19+
20+
/**
21+
* @var \Psr\Http\Message\ResponseFactoryInterface
22+
*/
23+
protected $responseFactory;
24+
25+
/**
26+
* @var int
27+
*/
28+
protected $status;
29+
30+
/**
31+
* EmptyResponseHandler constructor.
32+
*
33+
* @param \Psr\Http\Message\ResponseFactoryInterface $responseFactory
34+
* @param int $status
35+
*/
36+
public function __construct(ResponseFactoryInterface $responseFactory, int $status){
37+
$this->responseFactory = $responseFactory;
38+
$this->status = $status;
39+
}
40+
41+
/**
42+
* @inheritDoc
43+
*/
44+
public function handle(ServerRequestInterface $request):ResponseInterface{
45+
return $this->responseFactory->createResponse($this->status);
46+
}
47+
48+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
/**
3+
* Class MiddlewareException
4+
*
5+
* @filesource MiddlewareException.php
6+
* @created 10.03.2019
7+
* @package chillerlan\HTTP\Psr15\Middleware
8+
* @author smiley <[email protected]>
9+
* @copyright 2019 smiley
10+
* @license MIT
11+
*/
12+
13+
namespace chillerlan\HTTP\Psr15\Middleware;
14+
15+
class MiddlewareException extends \Exception{}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
/**
3+
* Class PriorityMiddleware
4+
*
5+
* @filesource PriorityMiddleware.php
6+
* @created 10.03.2019
7+
* @package chillerlan\HTTP\Psr15\Middleware
8+
* @author smiley <[email protected]>
9+
* @copyright 2019 smiley
10+
* @license MIT
11+
*/
12+
13+
namespace chillerlan\HTTP\Psr15\Middleware;
14+
15+
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
16+
use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface};
17+
18+
class PriorityMiddleware implements PriorityMiddlewareInterface{
19+
20+
/**
21+
* @var \Psr\Http\Server\MiddlewareInterface
22+
*/
23+
protected $middleware;
24+
25+
/**
26+
* @var int
27+
*/
28+
protected $priority;
29+
30+
/**
31+
* PriorityMiddleware constructor.
32+
*
33+
* @param \Psr\Http\Server\MiddlewareInterface $middleware
34+
* @param int|null $priority
35+
*/
36+
public function __construct(MiddlewareInterface $middleware, int $priority = null){
37+
$this->middleware = $middleware;
38+
$this->priority = $priority ?? PHP_INT_MIN;
39+
}
40+
41+
/**
42+
* @inheritDoc
43+
*/
44+
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler):ResponseInterface{
45+
return $this->middleware->process($request, $handler);
46+
}
47+
48+
/**
49+
* @inheritDoc
50+
*/
51+
public function getPriority():int{
52+
return $this->priority;
53+
}
54+
55+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
/**
3+
* Interface PriorityMiddlewareInterface
4+
*
5+
* @filesource PriorityMiddlewareInterface.php
6+
* @created 10.03.2019
7+
* @package chillerlan\HTTP\Psr15\Middleware
8+
* @author smiley <[email protected]>
9+
* @copyright 2019 smiley
10+
* @license MIT
11+
*/
12+
13+
namespace chillerlan\HTTP\Psr15\Middleware;
14+
15+
use Psr\Http\Server\MiddlewareInterface;
16+
17+
interface PriorityMiddlewareInterface extends MiddlewareInterface{
18+
19+
/**
20+
* @return int
21+
*/
22+
public function getPriority():int;
23+
24+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
/**
3+
* Class PriorityQueueRequestHandler
4+
*
5+
* @link https://github.com/libreworks/caridea-dispatch
6+
*
7+
* @filesource PriorityQueueRequestHandler.php
8+
* @created 10.03.2019
9+
* @package chillerlan\HTTP\Psr15
10+
* @author smiley <[email protected]>
11+
* @copyright 2019 smiley
12+
* @license MIT
13+
*/
14+
15+
namespace chillerlan\HTTP\Psr15;
16+
17+
use chillerlan\HTTP\Psr15\Middleware\{MiddlewareException, PriorityMiddleware, PriorityMiddlewareInterface};
18+
use Psr\Http\Server\MiddlewareInterface;
19+
20+
class PriorityQueueRequestHandler extends QueueRequestHandler{
21+
22+
/**
23+
* @inheritDoc
24+
*/
25+
public function addStack(iterable $middlewareStack):QueueRequestHandler{
26+
27+
foreach($middlewareStack as $middleware){
28+
29+
if(!$middleware instanceof MiddlewareInterface){
30+
throw new MiddlewareException('invalid middleware');
31+
}
32+
33+
if(!$middleware instanceof PriorityMiddlewareInterface){
34+
$middleware = new PriorityMiddleware($middleware);
35+
}
36+
37+
$this->middlewareStack[] = $middleware;
38+
}
39+
40+
$this->sortMiddleware();
41+
42+
return $this;
43+
}
44+
45+
/**
46+
* @inheritDoc
47+
*/
48+
public function add(MiddlewareInterface $middleware):QueueRequestHandler{
49+
50+
if(!$middleware instanceof PriorityMiddlewareInterface){
51+
$middleware = new PriorityMiddleware($middleware);
52+
}
53+
54+
$this->middlewareStack[] = $middleware;
55+
56+
$this->sortMiddleware();
57+
58+
return $this;
59+
}
60+
61+
/**
62+
* @return void
63+
*/
64+
protected function sortMiddleware():void{
65+
usort($this->middlewareStack, function(PriorityMiddlewareInterface $a, PriorityMiddlewareInterface $b){
66+
return $a->getPriority() > $b->getPriority();
67+
});
68+
}
69+
70+
}

src/Psr15/QueueRequestHandler.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
/**
3+
* Class QueueRequestHandler
4+
*
5+
* @link https://github.com/libreworks/caridea-dispatch
6+
*
7+
* @filesource QueueRequestHandler.php
8+
* @created 08.03.2019
9+
* @package chillerlan\HTTP\Psr15
10+
* @author smiley <[email protected]>
11+
* @copyright 2019 smiley
12+
* @license MIT
13+
*/
14+
15+
namespace chillerlan\HTTP\Psr15;
16+
17+
use chillerlan\HTTP\Psr15\Middleware\MiddlewareException;
18+
use chillerlan\HTTP\Psr17\ResponseFactory;
19+
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
20+
use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface};
21+
22+
class QueueRequestHandler implements MiddlewareInterface, RequestHandlerInterface{
23+
24+
/**
25+
* @var \Psr\Http\Server\MiddlewareInterface[]
26+
*/
27+
protected $middlewareStack = [];
28+
29+
/**
30+
* @var \Psr\Http\Server\RequestHandlerInterface
31+
*/
32+
protected $fallbackHandler;
33+
34+
/**
35+
* QueueRequestHandler constructor.
36+
*
37+
* @param iterable|null $middlewareStack
38+
* @param \Psr\Http\Server\RequestHandlerInterface|null $fallbackHandler
39+
*/
40+
public function __construct(iterable $middlewareStack = null, RequestHandlerInterface $fallbackHandler = null){
41+
$this->fallbackHandler = $fallbackHandler ?? new EmptyResponseHandler(new ResponseFactory, 500);
42+
43+
$this->addStack($middlewareStack ?? []);
44+
}
45+
46+
/**
47+
* @param iterable|\Psr\Http\Server\MiddlewareInterface[] $middlewareStack
48+
*
49+
* @return \chillerlan\HTTP\Psr15\QueueRequestHandler
50+
* @throws \Exception
51+
*/
52+
public function addStack(iterable $middlewareStack):QueueRequestHandler{
53+
54+
foreach($middlewareStack as $middleware){
55+
56+
if(!$middleware instanceof MiddlewareInterface){
57+
throw new MiddlewareException('invalid middleware');
58+
}
59+
60+
$this->middlewareStack[] = $middleware;
61+
}
62+
63+
return $this;
64+
}
65+
66+
/**
67+
* @param \Psr\Http\Server\MiddlewareInterface $middleware
68+
*
69+
* @return \chillerlan\HTTP\Psr15\QueueRequestHandler
70+
*/
71+
public function add(MiddlewareInterface $middleware):QueueRequestHandler{
72+
$this->middlewareStack[] = $middleware;
73+
74+
return $this;
75+
}
76+
77+
/**
78+
* @inheritDoc
79+
*/
80+
public function handle(ServerRequestInterface $request):ResponseInterface{
81+
return (new QueueRunner($this->middlewareStack, $this->fallbackHandler))->handle($request);
82+
}
83+
84+
/**
85+
* @inheritDoc
86+
*/
87+
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler):ResponseInterface{
88+
return (new QueueRunner($this->middlewareStack, $handler))->handle($request);
89+
}
90+
91+
}

src/Psr15/QueueRunner.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
/**
3+
* Class QueueRunner
4+
*
5+
* @link https://www.php-fig.org/psr/psr-15/meta/
6+
*
7+
* @filesource QueueRunner.php
8+
* @created 10.03.2019
9+
* @package chillerlan\HTTP\Psr15
10+
* @author smiley <[email protected]>
11+
* @copyright 2019 smiley
12+
* @license MIT
13+
*/
14+
15+
namespace chillerlan\HTTP\Psr15;
16+
17+
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
18+
use Psr\Http\Server\RequestHandlerInterface;
19+
20+
class QueueRunner implements RequestHandlerInterface{
21+
22+
/**
23+
* @var \Psr\Http\Server\MiddlewareInterface[]
24+
*/
25+
private $middlewareStack;
26+
27+
/**
28+
* @var \Psr\Http\Server\RequestHandlerInterface
29+
*/
30+
private $fallbackHandler;
31+
32+
/**
33+
* constructor.
34+
*
35+
* @param array $middlewareStack
36+
* @param \Psr\Http\Server\RequestHandlerInterface $fallbackHandler
37+
*/
38+
public function __construct(array $middlewareStack, RequestHandlerInterface $fallbackHandler){
39+
$this->middlewareStack = $middlewareStack;
40+
$this->fallbackHandler = $fallbackHandler;
41+
}
42+
43+
/**
44+
* @inheritDoc
45+
*/
46+
public function handle(ServerRequestInterface $request):ResponseInterface{
47+
48+
if(empty($this->middlewareStack)){
49+
return $this->fallbackHandler->handle($request);
50+
}
51+
52+
$middleware = array_shift($this->middlewareStack);
53+
54+
return $middleware->process($request, $this);
55+
}
56+
57+
}

0 commit comments

Comments
 (0)