Browse Source

Set the request instance to the Router after each middleware is run.

This allows an error handleware middleware to pull the upto date request instance
from the route for response generation. Closes #17731.
ADmad 1 year ago
parent
commit
327f97a191

+ 1 - 1
src/Error/Middleware/ErrorHandlerMiddleware.php

@@ -116,7 +116,7 @@ class ErrorHandlerMiddleware implements MiddlewareInterface
         } catch (RedirectException $exception) {
             return $this->handleRedirect($exception);
         } catch (Throwable $exception) {
-            return $this->handleException($exception, $request);
+            return $this->handleException($exception, Router::getRequest() ?? $request);
         }
     }
 

+ 7 - 7
src/Http/Runner.php

@@ -57,13 +57,6 @@ class Runner implements RequestHandlerInterface
         $this->queue->rewind();
         $this->fallbackHandler = $fallbackHandler;
 
-        if (
-            $fallbackHandler instanceof RoutingApplicationInterface &&
-            $request instanceof ServerRequest
-        ) {
-            Router::setRequest($request);
-        }
-
         return $this->handle($request);
     }
 
@@ -75,6 +68,13 @@ class Runner implements RequestHandlerInterface
      */
     public function handle(ServerRequestInterface $request): ResponseInterface
     {
+        if (
+            $this->fallbackHandler instanceof RoutingApplicationInterface &&
+            $request instanceof ServerRequest
+        ) {
+            Router::setRequest($request);
+        }
+
         if ($this->queue->valid()) {
             $middleware = $this->queue->current();
             $this->queue->next();

+ 22 - 9
tests/TestCase/Http/RunnerTest.php

@@ -62,10 +62,10 @@ class RunnerTest extends TestCase
         $this->queue = new MiddlewareQueue();
 
         $this->ok = function ($request, $handler) {
-            return $handler->handle($request);
+            return $handler->handle($request->withAttribute('ok', true));
         };
         $this->pass = function ($request, $handler) {
-            return $handler->handle($request);
+            return $handler->handle($request->withAttribute('pass', true));
         };
         $this->fail = function ($request, $handler): void {
             throw new RuntimeException('A bad thing');
@@ -133,15 +133,28 @@ class RunnerTest extends TestCase
 
     public function testRunSetRouterContext(): void
     {
+        $attributes = [];
+
+        $this->queue
+            ->add(function ($request, $handler) use (&$attributes) {
+                try {
+                    return $handler->handle($request);
+                } catch (Throwable) {
+                    $request = Router::getRequest();
+
+                    $attributes['pass'] = $request->getAttribute('pass');
+                    $attributes['ok'] = $request->getAttribute('ok');
+                }
+
+                return new Response();
+            })
+            ->add($this->ok)
+            ->add($this->pass)
+            ->add($this->fail);
         $runner = new Runner();
-        $request = new ServerRequest();
         $app = new Application(CONFIG);
 
-        try {
-            $runner->run($this->queue, $request, $app);
-        } catch (Throwable $e) {
-        }
-
-        $this->assertSame($request, Router::getRequest());
+        $runner->run($this->queue, new ServerRequest(), $app);
+        $this->assertSame(['pass' => true, 'ok' => true], $attributes);
     }
 }