/
App.php
191 lines (172 loc) · 5.71 KB
/
App.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim/blob/4.x/LICENSE.md (MIT License)
*/
declare(strict_types=1);
namespace Slim;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\Factory\ServerRequestCreatorFactory;
use Slim\Interfaces\CallableResolverInterface;
use Slim\Interfaces\RouteCollectorInterface;
use Slim\Interfaces\RouteResolverInterface;
use Slim\Middleware\ErrorMiddleware;
use Slim\Middleware\RoutingMiddleware;
use Slim\Routing\RouteCollectorProxy;
use Slim\Routing\RouteResolver;
use Slim\Routing\RouteRunner;
class App extends RouteCollectorProxy implements RequestHandlerInterface
{
/**
* Current version
*
* @var string
*/
public const VERSION = '4.1.0';
/**
* @var MiddlewareDispatcher
*/
protected $middlewareDispatcher;
/**
* @var RouteResolverInterface
*/
protected $routeResolver;
/**
* @param ResponseFactoryInterface $responseFactory
* @param ContainerInterface|null $container
* @param CallableResolverInterface|null $callableResolver
* @param RouteCollectorInterface|null $routeCollector
* @param RouteResolverInterface|null $routeResolver
*/
public function __construct(
ResponseFactoryInterface $responseFactory,
?ContainerInterface $container = null,
?CallableResolverInterface $callableResolver = null,
?RouteCollectorInterface $routeCollector = null,
?RouteResolverInterface $routeResolver = null
) {
parent::__construct(
$responseFactory,
$callableResolver ?? new CallableResolver($container),
$container,
$routeCollector
);
$this->routeResolver = $routeResolver ?? new RouteResolver($this->routeCollector);
$routeRunner = new RouteRunner($this->routeResolver, $this->routeCollector->getRouteParser());
$this->middlewareDispatcher = new MiddlewareDispatcher($routeRunner, $this->callableResolver, $container);
}
/**
* @return RouteResolverInterface
*/
public function getRouteResolver(): RouteResolverInterface
{
return $this->routeResolver;
}
/**
* @param MiddlewareInterface|string|callable $middleware
* @return self
*/
public function add($middleware): self
{
$this->middlewareDispatcher->add($middleware);
return $this;
}
/**
* @param MiddlewareInterface $middleware
* @return self
*/
public function addMiddleware(MiddlewareInterface $middleware): self
{
$this->middlewareDispatcher->addMiddleware($middleware);
return $this;
}
/**
* Add the slim built-in routing middleware to the app middleware stack
*
* @return RoutingMiddleware
*/
public function addRoutingMiddleware(): RoutingMiddleware
{
$routingMiddleware = new RoutingMiddleware(
$this->getRouteResolver(),
$this->getRouteCollector()->getRouteParser()
);
$this->add($routingMiddleware);
return $routingMiddleware;
}
/**
* Add the slim built-in error middleware to the app middleware stack
*
* @param bool $displayErrorDetails
* @param bool $logErrors
* @param bool $logErrorDetails
*
* @return ErrorMiddleware
*/
public function addErrorMiddleware(
bool $displayErrorDetails,
bool $logErrors,
bool $logErrorDetails
): ErrorMiddleware {
$errorMiddleware = new ErrorMiddleware(
$this->getCallableResolver(),
$this->getResponseFactory(),
$displayErrorDetails,
$logErrors,
$logErrorDetails
);
$this->add($errorMiddleware);
return $errorMiddleware;
}
/**
* Run application
*
* This method traverses the application middleware stack and then sends the
* resultant Response object to the HTTP client.
*
* @param ServerRequestInterface|null $request
* @return void
*/
public function run(?ServerRequestInterface $request = null): void
{
if (!$request) {
$serverRequestCreator = ServerRequestCreatorFactory::create();
$request = $serverRequestCreator->createServerRequestFromGlobals();
}
$response = $this->handle($request);
$responseEmitter = new ResponseEmitter();
$responseEmitter->emit($response);
}
/**
* Handle a request
*
* This method traverses the application middleware stack and then returns the
* resultant Response object.
*
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
public function handle(ServerRequestInterface $request): ResponseInterface
{
$response = $this->middlewareDispatcher->handle($request);
/**
* This is to be in compliance with RFC 2616, Section 9.
* If the incoming request method is HEAD, we need to ensure that the response body
* is empty as the request may fall back on a GET route handler due to FastRoute's
* routing logic which could potentially append content to the response body
* https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4
*/
$method = strtoupper($request->getMethod());
if ($method === 'HEAD') {
$emptyBody = $this->responseFactory->createResponse()->getBody();
return $response->withBody($emptyBody);
}
return $response;
}
}