• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

slimphp / Slim / 19799276323

30 Nov 2025 01:02PM UTC coverage: 97.317% (-1.5%) from 98.808%
19799276323

Pull #3417

github

web-flow
Merge 978880a0d into 626bbbdde
Pull Request #3417: 5.x - Refactor internals to improve routing and middleware handling

158 of 171 new or added lines in 22 files covered. (92.4%)

4 existing lines in 2 files now uncovered.

943 of 969 relevant lines covered (97.32%)

34.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.67
/Slim/Middleware/EndpointMiddleware.php
1
<?php
2

3
namespace Slim\Middleware;
4

5
use Psr\Http\Message\ResponseInterface;
6
use Psr\Http\Message\ServerRequestInterface;
7
use Psr\Http\Server\MiddlewareInterface;
8
use Psr\Http\Server\RequestHandlerInterface;
9
use RuntimeException;
10
use Slim\Exception\HttpMethodNotAllowedException;
11
use Slim\Exception\HttpNotFoundException;
12
use Slim\Routing\PipelineRunner;
13
use Slim\Routing\Route;
14
use Slim\Routing\RouteContext;
15
use Slim\Routing\RouteInvoker;
16
use Slim\Routing\RoutingResults;
17

18
/**
19
 * This middleware processes the routing results to determine if a route was found,
20
 * if the HTTP method is allowed, or if the route was not found. Based on these results,
21
 * it either executes the found route's handler with its associated middleware stack or
22
 * throws appropriate exceptions for 404 Not Found or 405 Method Not Allowed.
23
 */
24
final class EndpointMiddleware implements MiddlewareInterface
25
{
26
    private RouteInvoker $routeInvoker;
27

28
    private PipelineRunner $pipelineRunner;
29

30
    public function __construct(
31
        RouteInvoker $routeInvoker,
32
        PipelineRunner $pipelineRunner,
33
    ) {
34
        $this->routeInvoker = $routeInvoker;
89✔
35
        $this->pipelineRunner = $pipelineRunner;
89✔
36
    }
37

38
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
39
    {
40
        /* @var RoutingResults $routingResults */
41
        $routingResults = $request->getAttribute(RouteContext::ROUTING_RESULTS);
89✔
42

43
        if (!$routingResults instanceof RoutingResults) {
89✔
44
            throw new RuntimeException(
×
NEW
45
                'An unexpected error occurred while handling routing results. Routing results are not available.',
×
46
            );
×
47
        }
48

49
        $routeStatus = $routingResults->getRouteStatus();
89✔
50
        if ($routeStatus === RoutingResults::FOUND) {
89✔
51
            return $this->handleFound($request, $routingResults);
83✔
52
        }
53

54
        if ($routeStatus === RoutingResults::NOT_FOUND) {
6✔
55
            // 404 Not Found
56
            throw new HttpNotFoundException($request);
3✔
57
        }
58

59
        if ($routeStatus === RoutingResults::METHOD_NOT_ALLOWED) {
3✔
60
            // 405 Method Not Allowed
61
            $exception = new HttpMethodNotAllowedException($request);
3✔
62
            $exception->setAllowedMethods($routingResults->getAllowedMethods());
3✔
63

64
            throw $exception;
3✔
65
        }
66

67
        throw new RuntimeException('An unexpected error occurred while endpoint handling.');
×
68
    }
69

70
    private function handleFound(
71
        ServerRequestInterface $request,
72
        RoutingResults $routingResults,
73
    ): ResponseInterface {
74
        $route = $routingResults->getRoute() ?? throw new RuntimeException('Route not found.');
83✔
75

76
        // Collect route specific middleware
77
        $pipeline = $this->collectRouteMiddleware($route);
83✔
78

79
        // Invoke the route/group specific middleware stack
80
        $pipeline[] = $this->routeInvoker->withHandler(
83✔
81
            $route->getHandler(),
83✔
82
            $routingResults->getRouteArguments(),
83✔
83
        );
83✔
84

85
        return $this->pipelineRunner->withPipeline($pipeline)->handle($request);
82✔
86
    }
87

88
    /**
89
     * @param Route $route
90
     * @return array<MiddlewareInterface|callable|string> List of middleware
91
     */
92
    private function collectRouteMiddleware(Route $route): array
93
    {
94
        $middlewares = [];
83✔
95

96
        // Append group specific middleware from all parent route groups
97
        $group = $route->getRouteGroup();
83✔
98

99
        while ($group) {
83✔
100
            // Prepend group middleware so outer groups come first
101
            $middlewares = array_merge($group->getMiddleware(), $middlewares);
2✔
102
            $group = $group->getRouteGroup();
2✔
103
        }
104

105
        // Append endpoint-specific middleware
106
        return array_merge($middlewares, $route->getMiddleware());
83✔
107
    }
108

109
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc