Code Coverage |
||||||||||||||||
Lines |
Branches |
Paths |
Functions and Methods |
Classes and Traits |
||||||||||||
| Total | |
100.00% |
102 / 102 |
|
98.90% |
90 / 91 |
|
45.35% |
39 / 86 |
|
96.55% |
28 / 29 |
CRAP | |
0.00% |
0 / 1 |
| App | |
100.00% |
102 / 102 |
|
98.90% |
90 / 91 |
|
45.35% |
39 / 86 |
|
100.00% |
29 / 29 |
475.56 | |
100.00% |
1 / 1 |
| __construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| load | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| create | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| router | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| factory | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| addRoute | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| group | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| staticRoute | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getMiddleware | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| errorHandler | |
100.00% |
3 / 3 |
|
100.00% |
3 / 3 |
|
50.00% |
1 / 2 |
|
100.00% |
1 / 1 |
2.50 | |||
| emitter | |
100.00% |
3 / 3 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| middleware | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| before | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| after | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| logger | |
100.00% |
3 / 3 |
|
100.00% |
4 / 4 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| container | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| register | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| initializeContainer | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| teardown | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| handle | |
100.00% |
6 / 6 |
|
100.00% |
5 / 5 |
|
0.00% |
0 / 3 |
|
100.00% |
1 / 1 |
2 | |||
| run | |
100.00% |
13 / 13 |
|
100.00% |
9 / 9 |
|
0.00% |
0 / 6 |
|
100.00% |
1 / 1 |
3 | |||
| serve | |
100.00% |
7 / 7 |
|
100.00% |
5 / 5 |
|
50.00% |
2 / 4 |
|
100.00% |
1 / 1 |
4.12 | |||
| reusable | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| respond | |
100.00% |
8 / 8 |
|
100.00% |
4 / 4 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| endRequest | |
100.00% |
2 / 2 |
|
100.00% |
3 / 3 |
|
50.00% |
1 / 2 |
|
100.00% |
1 / 1 |
2.50 | |||
| finish | |
100.00% |
11 / 11 |
|
100.00% |
13 / 13 |
|
13.64% |
3 / 22 |
|
100.00% |
1 / 1 |
21.10 | |||
| report | |
100.00% |
9 / 9 |
|
100.00% |
12 / 12 |
|
33.33% |
4 / 12 |
|
100.00% |
1 / 1 |
12.41 | |||
| recordServerException | |
100.00% |
2 / 2 |
|
83.33% |
5 / 6 |
|
25.00% |
1 / 4 |
|
100.00% |
1 / 1 |
3.69 | |||
| emitFailure | |
100.00% |
7 / 7 |
|
100.00% |
7 / 7 |
|
50.00% |
4 / 8 |
|
100.00% |
1 / 1 |
6.00 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Celema\Core; |
| 6 | |
| 7 | use Celema\Container\Container; |
| 8 | use Celema\Container\Entry; |
| 9 | use Celema\Container\Exception\ResetFailed; |
| 10 | use Celema\Core\Emitter\Emitter; |
| 11 | use Celema\Core\Emitter\Fallback; |
| 12 | use Celema\Core\Emitter\Sapi; |
| 13 | use Celema\Core\Error\Handler as ErrorHandler; |
| 14 | use Celema\Core\Error\Log; |
| 15 | use Celema\Core\Factory\Factory; |
| 16 | use Celema\Core\Factory\Nyholm; |
| 17 | use Celema\Core\Runtime\FrankenPhpWorker; |
| 18 | use Celema\Router\AddsRoutes; |
| 19 | use Celema\Router\After; |
| 20 | use Celema\Router\Before; |
| 21 | use Celema\Router\Dispatcher; |
| 22 | use Celema\Router\Route; |
| 23 | use Celema\Router\RouteAdder; |
| 24 | use Celema\Router\Router; |
| 25 | use Celema\Router\RoutingHandler; |
| 26 | use Celema\Server\Console as ServerConsole; |
| 27 | use Closure; |
| 28 | use Override; |
| 29 | use Psr\Container\ContainerInterface as PsrContainer; |
| 30 | use Psr\Http\Message\ResponseInterface as Response; |
| 31 | use Psr\Http\Message\ServerRequestInterface as Request; |
| 32 | use Psr\Http\Server\MiddlewareInterface as Middleware; |
| 33 | use Psr\Http\Server\RequestHandlerInterface as RequestHandler; |
| 34 | use Psr\Log\LoggerInterface as Logger; |
| 35 | use Psr\Log\LogLevel; |
| 36 | use Throwable; |
| 37 | |
| 38 | /** @api */ |
| 39 | class App implements RouteAdder, RequestHandler |
| 40 | { |
| 41 | use AddsRoutes; |
| 42 | |
| 43 | protected readonly Dispatcher $dispatcher; |
| 44 | protected ?ErrorHandler $errorHandler = null; |
| 45 | protected Emitter $emitter; |
| 46 | |
| 47 | /** @var list<Closure(): void> */ |
| 48 | protected array $teardownHooks = []; |
| 49 | |
| 50 | /** |
| 51 | * False once a request left state behind that the app cannot vouch for: |
| 52 | * a throwable escaped the request, or its teardown failed. |
| 53 | */ |
| 54 | protected bool $reusable = true; |
| 55 | |
| 56 | public function __construct( |
| 57 | protected readonly Factory $factory, |
| 58 | protected readonly Router $router, |
| 59 | protected readonly Container $container, |
| 60 | ) { |
| 61 | $this->dispatcher = new Dispatcher(); |
| 62 | $this->emitter = new Sapi(); |
| 63 | $this->initializeContainer(); |
| 64 | } |
| 65 | |
| 66 | public function load(Plugin $plugin): void |
| 67 | { |
| 68 | $plugin->load($this); |
| 69 | } |
| 70 | |
| 71 | public static function create(?PsrContainer $container = null): self |
| 72 | { |
| 73 | return new self( |
| 74 | new Nyholm(), |
| 75 | new Router(), |
| 76 | new Container(container: $container), |
| 77 | ); |
| 78 | } |
| 79 | |
| 80 | public function router(): Router |
| 81 | { |
| 82 | return $this->router; |
| 83 | } |
| 84 | |
| 85 | public function factory(): Factory |
| 86 | { |
| 87 | return $this->factory; |
| 88 | } |
| 89 | |
| 90 | #[Override] |
| 91 | public function addRoute(Route $route): Route |
| 92 | { |
| 93 | return $this->router->addRoute($route); |
| 94 | } |
| 95 | |
| 96 | #[Override] |
| 97 | public function group( |
| 98 | string $patternPrefix, |
| 99 | Closure $createClosure, |
| 100 | string $namePrefix = '', |
| 101 | ): void { |
| 102 | $this->router->group($patternPrefix, $createClosure, $namePrefix); |
| 103 | } |
| 104 | |
| 105 | public function staticRoute( |
| 106 | string $prefix, |
| 107 | string $path, |
| 108 | string $name = '', |
| 109 | ): void { |
| 110 | $this->router->addStatic($prefix, $path, $name); |
| 111 | } |
| 112 | |
| 113 | /** @return list<Middleware> */ |
| 114 | public function getMiddleware(): array |
| 115 | { |
| 116 | return $this->dispatcher->getMiddleware(); |
| 117 | } |
| 118 | |
| 119 | public function errorHandler(?ErrorHandler $handler = null): ?ErrorHandler |
| 120 | { |
| 121 | if ($handler !== null) { |
| 122 | $this->errorHandler = $handler; |
| 123 | } |
| 124 | |
| 125 | return $this->errorHandler; |
| 126 | } |
| 127 | |
| 128 | public function emitter(?Emitter $emitter = null): Emitter |
| 129 | { |
| 130 | if ($emitter !== null) { |
| 131 | $this->emitter = $emitter; |
| 132 | } |
| 133 | |
| 134 | return $this->emitter; |
| 135 | } |
| 136 | |
| 137 | public function middleware(Middleware ...$middleware): void |
| 138 | { |
| 139 | $this->dispatcher->middleware(...$middleware); |
| 140 | } |
| 141 | |
| 142 | public function before(Before $beforeHandler): static |
| 143 | { |
| 144 | $this->dispatcher->before($beforeHandler); |
| 145 | |
| 146 | return $this; |
| 147 | } |
| 148 | |
| 149 | public function after(After $afterHandler): static |
| 150 | { |
| 151 | $this->dispatcher->after($afterHandler); |
| 152 | |
| 153 | return $this; |
| 154 | } |
| 155 | |
| 156 | public function logger(Logger|callable $logger): void |
| 157 | { |
| 158 | if ($logger instanceof Logger) { |
| 159 | $this->container->add(Logger::class, $logger); |
| 160 | } else { |
| 161 | $this->container->add(Logger::class, Closure::fromCallable($logger)); |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | public function container(): Container |
| 166 | { |
| 167 | return $this->container; |
| 168 | } |
| 169 | |
| 170 | /** |
| 171 | * @param non-empty-string $key |
| 172 | * @param class-string|object $value |
| 173 | */ |
| 174 | public function register(string $key, object|string $value): Entry |
| 175 | { |
| 176 | return $this->container->add($key, $value); |
| 177 | } |
| 178 | |
| 179 | public function initializeContainer(): void |
| 180 | { |
| 181 | $this->container->add(Router::class, $this->router); |
| 182 | $this->container->add($this->router::class, $this->router); |
| 183 | |
| 184 | $this->container->add(Factory::class, $this->factory); |
| 185 | $this->container->add($this->factory::class, $this->factory); |
| 186 | } |
| 187 | |
| 188 | /** |
| 189 | * Registers a callback that runs after every request, once the request's |
| 190 | * container scope was reset: in run() after the response was emitted and, |
| 191 | * where the runtime allows, the request ended, so the client does not |
| 192 | * wait for it; in handle() before the response is returned. Use it to |
| 193 | * bring resources that outlive a request back to a clean state, such as |
| 194 | * rolling back a database transaction left open, or for work the client |
| 195 | * need not wait for. |
| 196 | * |
| 197 | * Callbacks run in registration order. A failing callback does not stop |
| 198 | * the others; failures are logged and the app is no longer reusable. |
| 199 | * |
| 200 | * @param Closure(): void $hook |
| 201 | */ |
| 202 | public function teardown(Closure $hook): void |
| 203 | { |
| 204 | $this->teardownHooks[] = $hook; |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * Handles the request in its own container scope without emitting the |
| 209 | * response. The scope is reset and the teardown hooks have run when the |
| 210 | * response is returned, so its body must not depend on scoped services. |
| 211 | */ |
| 212 | #[Override] |
| 213 | public function handle(Request $request): Response |
| 214 | { |
| 215 | $scope = $this->container->scope(); |
| 216 | |
| 217 | try { |
| 218 | return $this->respond($request, $scope); |
| 219 | } catch (Throwable $e) { |
| 220 | $this->reusable = false; |
| 221 | |
| 222 | throw $e; |
| 223 | } finally { |
| 224 | $this->finish($scope, $request); |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | /** |
| 229 | * Handles exactly one request in its own container scope, emits the |
| 230 | * response, ends the request, then runs the teardown. Throwables that |
| 231 | * escape the error handler or the emitter are logged and answered with a |
| 232 | * minimal 500 response if nothing was sent yet; they do not leave this |
| 233 | * method. |
| 234 | */ |
| 235 | public function run(?Request $request = null): Response|false |
| 236 | { |
| 237 | $bufferLevel = ob_get_level(); |
| 238 | $scope = $this->container->scope(); |
| 239 | |
| 240 | try { |
| 241 | $request ??= $this->factory->serverRequest(); |
| 242 | $response = $this->respond($request, $scope); |
| 243 | |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 245 | } catch (Throwable $e) { |
| 246 | $this->reusable = false; |
| 247 | $this->report('Unhandled exception', $e, $request); |
| 248 | $this->recordServerException($e); |
| 249 | // The method is unknown if creating the request failed. |
| 250 | $this->emitFailure($bufferLevel, $e, $request?->getMethod() === 'HEAD'); |
| 251 | |
| 252 | return false; |
| 253 | } finally { |
| 254 | $this->endRequest(); |
| 255 | $this->finish($scope, $request); |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | /** |
| 260 | * Runs the app in the runtime that started the script: as a FrankenPHP |
| 261 | * worker, which handles requests until it retires, or for exactly one |
| 262 | * request (PHP-FPM, FrankenPHP's classic mode, the CLI server). |
| 263 | * |
| 264 | * Register everything before calling it. The first request seals the |
| 265 | * container, so later registrations fail. |
| 266 | * |
| 267 | * @param ?int $maxRequests Worker only: retire after this many requests; 0 never. |
| 268 | * Defaults to the CELEMA_WORKER_MAX_REQUESTS environment variable, else 0. |
| 269 | * @param ?int $maxMemory Worker only: retire above this many bytes of memory; 0 never. |
| 270 | * Defaults to the CELEMA_WORKER_MAX_MEMORY environment variable, else 80 % of memory_limit. |
| 271 | */ |
| 272 | public function serve(?int $maxRequests = null, ?int $maxMemory = null): Response|false |
| 273 | { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 275 | return FrankenPhpWorker::configure( |
| 276 | frankenphp_handle_request(...), |
| 277 | $maxRequests, |
| 278 | $maxMemory, |
| 279 | )->serve($this); |
| 280 | } |
| 281 | |
| 282 | return $this->run(); |
| 283 | } |
| 284 | |
| 285 | /** |
| 286 | * Whether the app may handle further requests in the same process. |
| 287 | * |
| 288 | * @internal |
| 289 | */ |
| 290 | public function reusable(): bool |
| 291 | { |
| 292 | return $this->reusable; |
| 293 | } |
| 294 | |
| 295 | protected function respond(Request $request, Container $scope): Response |
| 296 | { |
| 297 | $handler = new RoutingHandler( |
| 298 | $this->router, |
| 299 | $this->dispatcher, |
| 300 | $scope, |
| 301 | ); |
| 302 | |
| 303 | return $this->errorHandler |
| 304 | ? $this->errorHandler->process($request, $handler) |
| 305 | : $handler->handle($request); |
| 306 | } |
| 307 | |
| 308 | /** |
| 309 | * Sends the emitted response to the client and closes the connection; |
| 310 | * the script goes on with the teardown. PHP-FPM and FrankenPHP, in both |
| 311 | * modes, provide the function; elsewhere the client waits for the teardown. |
| 312 | */ |
| 313 | protected function endRequest(): void |
| 314 | { |
| 315 | if (function_exists('fastcgi_finish_request')) { |
| 316 | fastcgi_finish_request(); |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | /** |
| 321 | * Resets the request scope, then runs the teardown hooks. Every step is |
| 322 | * attempted; failures are logged and make the app unusable for further |
| 323 | * requests, but never replace the request's response or exception. |
| 324 | */ |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | /** |
| 350 | * Logs a failure the error handler did not answer, naming the request |
| 351 | * it belongs to. The request is unknown when creating it failed. |
| 352 | */ |
| 353 | protected function report(string $message, Throwable $exception, ?Request $request): void |
| 354 | { |
| 355 | try { |
| 356 | /** @var mixed $logger */ |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 358 | } catch (Throwable $e) { |
| 359 | // A logger that cannot be resolved must not keep the failure from |
| 360 | // being answered or the request from being torn down. |
| 361 | error_log('Logging failed: ' . (string) $e); |
| 362 | $logger = null; |
| 363 | } |
| 364 | |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 368 | $message .= ' for {method} {path}'; |
| 369 | $values = Log::request($request); |
| 370 | } |
| 371 | |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 374 | |
| 375 | protected function recordServerException(Throwable $exception): void |
| 376 | { |
| 377 | // Shows the exception in the celema/server request log, as the error |
| 378 | // handler does for the exceptions it renders. |
| 379 | if (class_exists(ServerConsole::class)) { |
| 380 | ServerConsole::recordException($exception, trace: true); |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | /** |
| 385 | * Answers with a minimal 500 response if the failed request sent nothing |
| 386 | * yet. Like PHP for an uncaught exception, it shows the exception only |
| 387 | * while `display_errors` sends errors to the output, as in development. |
| 388 | */ |
| 389 | protected function emitFailure(int $bufferLevel, Throwable $exception, bool $withoutBody = false): void |
| 390 | { |
| 391 | $body = '500 Internal Server Error'; |
| 392 | $display = strtolower((string) ini_get('display_errors')); |
| 393 | |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 395 | $body .= "\n\n" . (string) $exception; |
| 396 | } |
| 397 | |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 399 | $response->getBody()->write($body); |
| 400 | |
| 401 | Fallback::emit($this->emitter, $response, $bufferLevel, $withoutBody); |
| 402 | } |
| 403 | } |
Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not
necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once.
Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement
always has an else as part of its logical flow even if you didn't write one.
| 57 | protected readonly Factory $factory, |
| 58 | protected readonly Router $router, |
| 59 | protected readonly Container $container, |
| 60 | ) { |
| 61 | $this->dispatcher = new Dispatcher(); |
| 62 | $this->emitter = new Sapi(); |
| 63 | $this->initializeContainer(); |
| 64 | } |
| 91 | public function addRoute(Route $route): Route |
| 92 | { |
| 93 | return $this->router->addRoute($route); |
| 94 | } |
| 149 | public function after(After $afterHandler): static |
| 150 | { |
| 151 | $this->dispatcher->after($afterHandler); |
| 152 | |
| 153 | return $this; |
| 154 | } |
| 142 | public function before(Before $beforeHandler): static |
| 143 | { |
| 144 | $this->dispatcher->before($beforeHandler); |
| 145 | |
| 146 | return $this; |
| 147 | } |
| 167 | return $this->container; |
| 168 | } |
| 71 | public static function create(?PsrContainer $container = null): self |
| 72 | { |
| 73 | return new self( |
| 74 | new Nyholm(), |
| 75 | new Router(), |
| 76 | new Container(container: $container), |
| 77 | ); |
| 78 | } |
| 389 | protected function emitFailure(int $bufferLevel, Throwable $exception, bool $withoutBody = false): void |
| 390 | { |
| 391 | $body = '500 Internal Server Error'; |
| 392 | $display = strtolower((string) ini_get('display_errors')); |
| 393 | |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 395 | $body .= "\n\n" . (string) $exception; |
| 396 | } |
| 397 | |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 399 | $response->getBody()->write($body); |
| 400 | |
| 401 | Fallback::emit($this->emitter, $response, $bufferLevel, $withoutBody); |
| 402 | } |
| 389 | protected function emitFailure(int $bufferLevel, Throwable $exception, bool $withoutBody = false): void |
| 390 | { |
| 391 | $body = '500 Internal Server Error'; |
| 392 | $display = strtolower((string) ini_get('display_errors')); |
| 393 | |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 399 | $response->getBody()->write($body); |
| 400 | |
| 401 | Fallback::emit($this->emitter, $response, $bufferLevel, $withoutBody); |
| 402 | } |
| 389 | protected function emitFailure(int $bufferLevel, Throwable $exception, bool $withoutBody = false): void |
| 390 | { |
| 391 | $body = '500 Internal Server Error'; |
| 392 | $display = strtolower((string) ini_get('display_errors')); |
| 393 | |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 395 | $body .= "\n\n" . (string) $exception; |
| 396 | } |
| 397 | |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 399 | $response->getBody()->write($body); |
| 400 | |
| 401 | Fallback::emit($this->emitter, $response, $bufferLevel, $withoutBody); |
| 402 | } |
| 389 | protected function emitFailure(int $bufferLevel, Throwable $exception, bool $withoutBody = false): void |
| 390 | { |
| 391 | $body = '500 Internal Server Error'; |
| 392 | $display = strtolower((string) ini_get('display_errors')); |
| 393 | |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 399 | $response->getBody()->write($body); |
| 400 | |
| 401 | Fallback::emit($this->emitter, $response, $bufferLevel, $withoutBody); |
| 402 | } |
| 389 | protected function emitFailure(int $bufferLevel, Throwable $exception, bool $withoutBody = false): void |
| 390 | { |
| 391 | $body = '500 Internal Server Error'; |
| 392 | $display = strtolower((string) ini_get('display_errors')); |
| 393 | |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 395 | $body .= "\n\n" . (string) $exception; |
| 396 | } |
| 397 | |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 399 | $response->getBody()->write($body); |
| 400 | |
| 401 | Fallback::emit($this->emitter, $response, $bufferLevel, $withoutBody); |
| 402 | } |
| 389 | protected function emitFailure(int $bufferLevel, Throwable $exception, bool $withoutBody = false): void |
| 390 | { |
| 391 | $body = '500 Internal Server Error'; |
| 392 | $display = strtolower((string) ini_get('display_errors')); |
| 393 | |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 399 | $response->getBody()->write($body); |
| 400 | |
| 401 | Fallback::emit($this->emitter, $response, $bufferLevel, $withoutBody); |
| 402 | } |
| 389 | protected function emitFailure(int $bufferLevel, Throwable $exception, bool $withoutBody = false): void |
| 390 | { |
| 391 | $body = '500 Internal Server Error'; |
| 392 | $display = strtolower((string) ini_get('display_errors')); |
| 393 | |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 395 | $body .= "\n\n" . (string) $exception; |
| 396 | } |
| 397 | |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 399 | $response->getBody()->write($body); |
| 400 | |
| 401 | Fallback::emit($this->emitter, $response, $bufferLevel, $withoutBody); |
| 402 | } |
| 389 | protected function emitFailure(int $bufferLevel, Throwable $exception, bool $withoutBody = false): void |
| 390 | { |
| 391 | $body = '500 Internal Server Error'; |
| 392 | $display = strtolower((string) ini_get('display_errors')); |
| 393 | |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 394 | if ($display !== 'stderr' && filter_var($display, FILTER_VALIDATE_BOOL) || $display === 'stdout') { |
| 398 | $response = $this->factory->response(500)->withHeader('Content-Type', 'text/plain; charset=utf-8'); |
| 399 | $response->getBody()->write($body); |
| 400 | |
| 401 | Fallback::emit($this->emitter, $response, $bufferLevel, $withoutBody); |
| 402 | } |
| 128 | public function emitter(?Emitter $emitter = null): Emitter |
| 129 | { |
| 130 | if ($emitter !== null) { |
| 131 | $this->emitter = $emitter; |
| 132 | } |
| 133 | |
| 134 | return $this->emitter; |
| 134 | return $this->emitter; |
| 135 | } |
| 128 | public function emitter(?Emitter $emitter = null): Emitter |
| 129 | { |
| 130 | if ($emitter !== null) { |
| 134 | return $this->emitter; |
| 135 | } |
| 315 | if (function_exists('fastcgi_finish_request')) { |
| 316 | fastcgi_finish_request(); |
| 317 | } |
| 318 | } |
| 318 | } |
| 315 | if (function_exists('fastcgi_finish_request')) { |
| 318 | } |
| 119 | public function errorHandler(?ErrorHandler $handler = null): ?ErrorHandler |
| 120 | { |
| 121 | if ($handler !== null) { |
| 122 | $this->errorHandler = $handler; |
| 123 | } |
| 124 | |
| 125 | return $this->errorHandler; |
| 125 | return $this->errorHandler; |
| 126 | } |
| 119 | public function errorHandler(?ErrorHandler $handler = null): ?ErrorHandler |
| 120 | { |
| 121 | if ($handler !== null) { |
| 125 | return $this->errorHandler; |
| 126 | } |
| 87 | return $this->factory; |
| 88 | } |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 325 | protected function finish(Container $scope, ?Request $request): void |
| 326 | { |
| 327 | $failures = []; |
| 328 | |
| 329 | try { |
| 330 | $scope->reset(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 331 | } catch (ResetFailed $e) { |
| 332 | $failures = $e->failures; |
| 333 | } |
| 334 | |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 338 | } catch (Throwable $e) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 338 | } catch (Throwable $e) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 338 | } catch (Throwable $e) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 338 | } catch (Throwable $e) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 335 | foreach ($this->teardownHooks as $hook) { |
| 336 | try { |
| 337 | $hook(); |
| 338 | } catch (Throwable $e) { |
| 339 | $failures[] = $e; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | foreach ($failures as $failure) { |
| 343 | foreach ($failures as $failure) { |
| 344 | $this->reusable = false; |
| 345 | $this->report('Request teardown failed', $failure, $request); |
| 346 | } |
| 347 | } |
| 116 | return $this->dispatcher->getMiddleware(); |
| 117 | } |
| 98 | string $patternPrefix, |
| 99 | Closure $createClosure, |
| 100 | string $namePrefix = '', |
| 101 | ): void { |
| 102 | $this->router->group($patternPrefix, $createClosure, $namePrefix); |
| 103 | } |
| 213 | public function handle(Request $request): Response |
| 214 | { |
| 215 | $scope = $this->container->scope(); |
| 216 | |
| 217 | try { |
| 218 | return $this->respond($request, $scope); |
| 224 | $this->finish($scope, $request); |
| 225 | } |
| 226 | } |
| 213 | public function handle(Request $request): Response |
| 214 | { |
| 215 | $scope = $this->container->scope(); |
| 216 | |
| 217 | try { |
| 218 | return $this->respond($request, $scope); |
| 218 | return $this->respond($request, $scope); |
| 219 | } catch (Throwable $e) { |
| 220 | $this->reusable = false; |
| 221 | |
| 222 | throw $e; |
| 181 | $this->container->add(Router::class, $this->router); |
| 182 | $this->container->add($this->router::class, $this->router); |
| 183 | |
| 184 | $this->container->add(Factory::class, $this->factory); |
| 185 | $this->container->add($this->factory::class, $this->factory); |
| 186 | } |
| 66 | public function load(Plugin $plugin): void |
| 67 | { |
| 68 | $plugin->load($this); |
| 69 | } |
| 156 | public function logger(Logger|callable $logger): void |
| 157 | { |
| 158 | if ($logger instanceof Logger) { |
| 158 | if ($logger instanceof Logger) { |
| 159 | $this->container->add(Logger::class, $logger); |
| 163 | } |
| 156 | public function logger(Logger|callable $logger): void |
| 157 | { |
| 158 | if ($logger instanceof Logger) { |
| 161 | $this->container->add(Logger::class, Closure::fromCallable($logger)); |
| 162 | } |
| 163 | } |
| 163 | } |
| 137 | public function middleware(Middleware ...$middleware): void |
| 138 | { |
| 139 | $this->dispatcher->middleware(...$middleware); |
| 140 | } |
| 375 | protected function recordServerException(Throwable $exception): void |
| 376 | { |
| 377 | // Shows the exception in the celema/server request log, as the error |
| 378 | // handler does for the exceptions it renders. |
| 379 | if (class_exists(ServerConsole::class)) { |
| 379 | if (class_exists(ServerConsole::class)) { |
| 379 | if (class_exists(ServerConsole::class)) { |
| 380 | ServerConsole::recordException($exception, trace: true); |
| 381 | } |
| 382 | } |
| 382 | } |
| 375 | protected function recordServerException(Throwable $exception): void |
| 376 | { |
| 377 | // Shows the exception in the celema/server request log, as the error |
| 378 | // handler does for the exceptions it renders. |
| 379 | if (class_exists(ServerConsole::class)) { |
| 379 | if (class_exists(ServerConsole::class)) { |
| 379 | if (class_exists(ServerConsole::class)) { |
| 382 | } |
| 375 | protected function recordServerException(Throwable $exception): void |
| 376 | { |
| 377 | // Shows the exception in the celema/server request log, as the error |
| 378 | // handler does for the exceptions it renders. |
| 379 | if (class_exists(ServerConsole::class)) { |
| 379 | if (class_exists(ServerConsole::class)) { |
| 379 | if (class_exists(ServerConsole::class)) { |
| 380 | ServerConsole::recordException($exception, trace: true); |
| 381 | } |
| 382 | } |
| 382 | } |
| 375 | protected function recordServerException(Throwable $exception): void |
| 376 | { |
| 377 | // Shows the exception in the celema/server request log, as the error |
| 378 | // handler does for the exceptions it renders. |
| 379 | if (class_exists(ServerConsole::class)) { |
| 379 | if (class_exists(ServerConsole::class)) { |
| 379 | if (class_exists(ServerConsole::class)) { |
| 382 | } |
| 174 | public function register(string $key, object|string $value): Entry |
| 175 | { |
| 176 | return $this->container->add($key, $value); |
| 177 | } |
| 353 | protected function report(string $message, Throwable $exception, ?Request $request): void |
| 354 | { |
| 355 | try { |
| 356 | /** @var mixed $logger */ |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 368 | $message .= ' for {method} {path}'; |
| 369 | $values = Log::request($request); |
| 370 | } |
| 371 | |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 353 | protected function report(string $message, Throwable $exception, ?Request $request): void |
| 354 | { |
| 355 | try { |
| 356 | /** @var mixed $logger */ |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 368 | $message .= ' for {method} {path}'; |
| 369 | $values = Log::request($request); |
| 370 | } |
| 371 | |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 353 | protected function report(string $message, Throwable $exception, ?Request $request): void |
| 354 | { |
| 355 | try { |
| 356 | /** @var mixed $logger */ |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 353 | protected function report(string $message, Throwable $exception, ?Request $request): void |
| 354 | { |
| 355 | try { |
| 356 | /** @var mixed $logger */ |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 353 | protected function report(string $message, Throwable $exception, ?Request $request): void |
| 354 | { |
| 355 | try { |
| 356 | /** @var mixed $logger */ |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 368 | $message .= ' for {method} {path}'; |
| 369 | $values = Log::request($request); |
| 370 | } |
| 371 | |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 353 | protected function report(string $message, Throwable $exception, ?Request $request): void |
| 354 | { |
| 355 | try { |
| 356 | /** @var mixed $logger */ |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 368 | $message .= ' for {method} {path}'; |
| 369 | $values = Log::request($request); |
| 370 | } |
| 371 | |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 353 | protected function report(string $message, Throwable $exception, ?Request $request): void |
| 354 | { |
| 355 | try { |
| 356 | /** @var mixed $logger */ |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 353 | protected function report(string $message, Throwable $exception, ?Request $request): void |
| 354 | { |
| 355 | try { |
| 356 | /** @var mixed $logger */ |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 357 | $logger = $this->container->has(Logger::class) ? $this->container->get(Logger::class) : null; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 358 | } catch (Throwable $e) { |
| 361 | error_log('Logging failed: ' . (string) $e); |
| 362 | $logger = null; |
| 363 | } |
| 364 | |
| 365 | $values = []; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 368 | $message .= ' for {method} {path}'; |
| 369 | $values = Log::request($request); |
| 370 | } |
| 371 | |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 358 | } catch (Throwable $e) { |
| 361 | error_log('Logging failed: ' . (string) $e); |
| 362 | $logger = null; |
| 363 | } |
| 364 | |
| 365 | $values = []; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 368 | $message .= ' for {method} {path}'; |
| 369 | $values = Log::request($request); |
| 370 | } |
| 371 | |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 358 | } catch (Throwable $e) { |
| 361 | error_log('Logging failed: ' . (string) $e); |
| 362 | $logger = null; |
| 363 | } |
| 364 | |
| 365 | $values = []; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 358 | } catch (Throwable $e) { |
| 361 | error_log('Logging failed: ' . (string) $e); |
| 362 | $logger = null; |
| 363 | } |
| 364 | |
| 365 | $values = []; |
| 365 | $values = []; |
| 366 | |
| 367 | if ($request !== null) { |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 372 | Log::write($logger instanceof Logger ? $logger : null, LogLevel::CRITICAL, $message, $exception, $values); |
| 373 | } |
| 295 | protected function respond(Request $request, Container $scope): Response |
| 296 | { |
| 297 | $handler = new RoutingHandler( |
| 298 | $this->router, |
| 299 | $this->dispatcher, |
| 300 | $scope, |
| 301 | ); |
| 302 | |
| 303 | return $this->errorHandler |
| 304 | ? $this->errorHandler->process($request, $handler) |
| 305 | : $handler->handle($request); |
| 306 | } |
| 295 | protected function respond(Request $request, Container $scope): Response |
| 296 | { |
| 297 | $handler = new RoutingHandler( |
| 298 | $this->router, |
| 299 | $this->dispatcher, |
| 300 | $scope, |
| 301 | ); |
| 302 | |
| 303 | return $this->errorHandler |
| 305 | : $handler->handle($request); |
| 305 | : $handler->handle($request); |
| 306 | } |
| 292 | return $this->reusable; |
| 293 | } |
| 82 | return $this->router; |
| 83 | } |
| 235 | public function run(?Request $request = null): Response|false |
| 236 | { |
| 237 | $bufferLevel = ob_get_level(); |
| 238 | $scope = $this->container->scope(); |
| 239 | |
| 240 | try { |
| 241 | $request ??= $this->factory->serverRequest(); |
| 242 | $response = $this->respond($request, $scope); |
| 243 | |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 254 | $this->endRequest(); |
| 255 | $this->finish($scope, $request); |
| 256 | } |
| 257 | } |
| 235 | public function run(?Request $request = null): Response|false |
| 236 | { |
| 237 | $bufferLevel = ob_get_level(); |
| 238 | $scope = $this->container->scope(); |
| 239 | |
| 240 | try { |
| 241 | $request ??= $this->factory->serverRequest(); |
| 242 | $response = $this->respond($request, $scope); |
| 243 | |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 235 | public function run(?Request $request = null): Response|false |
| 236 | { |
| 237 | $bufferLevel = ob_get_level(); |
| 238 | $scope = $this->container->scope(); |
| 239 | |
| 240 | try { |
| 241 | $request ??= $this->factory->serverRequest(); |
| 242 | $response = $this->respond($request, $scope); |
| 243 | |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 254 | $this->endRequest(); |
| 255 | $this->finish($scope, $request); |
| 256 | } |
| 257 | } |
| 235 | public function run(?Request $request = null): Response|false |
| 236 | { |
| 237 | $bufferLevel = ob_get_level(); |
| 238 | $scope = $this->container->scope(); |
| 239 | |
| 240 | try { |
| 241 | $request ??= $this->factory->serverRequest(); |
| 242 | $response = $this->respond($request, $scope); |
| 243 | |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 244 | return $this->emitter->emit($response, $request->getMethod() === 'HEAD') ? $response : false; |
| 245 | } catch (Throwable $e) { |
| 246 | $this->reusable = false; |
| 247 | $this->report('Unhandled exception', $e, $request); |
| 248 | $this->recordServerException($e); |
| 249 | // The method is unknown if creating the request failed. |
| 250 | $this->emitFailure($bufferLevel, $e, $request?->getMethod() === 'HEAD'); |
| 251 | |
| 252 | return false; |
| 254 | $this->endRequest(); |
| 255 | $this->finish($scope, $request); |
| 256 | } |
| 257 | } |
| 245 | } catch (Throwable $e) { |
| 246 | $this->reusable = false; |
| 247 | $this->report('Unhandled exception', $e, $request); |
| 248 | $this->recordServerException($e); |
| 249 | // The method is unknown if creating the request failed. |
| 250 | $this->emitFailure($bufferLevel, $e, $request?->getMethod() === 'HEAD'); |
| 251 | |
| 252 | return false; |
| 252 | return false; |
| 272 | public function serve(?int $maxRequests = null, ?int $maxMemory = null): Response|false |
| 273 | { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 275 | return FrankenPhpWorker::configure( |
| 276 | frankenphp_handle_request(...), |
| 277 | $maxRequests, |
| 278 | $maxMemory, |
| 279 | )->serve($this); |
| 272 | public function serve(?int $maxRequests = null, ?int $maxMemory = null): Response|false |
| 273 | { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 282 | return $this->run(); |
| 283 | } |
| 272 | public function serve(?int $maxRequests = null, ?int $maxMemory = null): Response|false |
| 273 | { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 275 | return FrankenPhpWorker::configure( |
| 276 | frankenphp_handle_request(...), |
| 277 | $maxRequests, |
| 278 | $maxMemory, |
| 279 | )->serve($this); |
| 272 | public function serve(?int $maxRequests = null, ?int $maxMemory = null): Response|false |
| 273 | { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 274 | if (isset($_SERVER['FRANKENPHP_WORKER']) && function_exists('frankenphp_handle_request')) { |
| 282 | return $this->run(); |
| 283 | } |
| 106 | string $prefix, |
| 107 | string $path, |
| 108 | string $name = '', |
| 109 | ): void { |
| 110 | $this->router->addStatic($prefix, $path, $name); |
| 111 | } |
| 202 | public function teardown(Closure $hook): void |
| 203 | { |
| 204 | $this->teardownHooks[] = $hook; |
| 205 | } |