summaryrefslogtreecommitdiff
path: root/src/Middleware/RouteDispatcher.php
blob: c20eba4bf40c7f1160f0f4cc8a7511c379448ef1 (plain)
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
<?php

namespace Engelsystem\Middleware;

use Engelsystem\Http\Request;
use FastRoute\Dispatcher as FastRouteDispatcher;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class RouteDispatcher implements MiddlewareInterface
{
    /** @var FastRouteDispatcher */
    protected $dispatcher;

    /** @var ResponseInterface */
    protected $response;

    /** @var MiddlewareInterface|null */
    protected $notFound;

    /**
     * @param FastRouteDispatcher      $dispatcher
     * @param ResponseInterface        $response Default response
     * @param MiddlewareInterface|null $notFound Handles any requests if the route can't be found
     */
    public function __construct(
        FastRouteDispatcher $dispatcher,
        ResponseInterface $response,
        MiddlewareInterface $notFound = null
    ) {
        $this->dispatcher = $dispatcher;
        $this->response = $response;
        $this->notFound = $notFound;
    }

    /**
     * Process an incoming server request and return a response, optionally delegating
     * response creation to a handler.
     *
     * @param ServerRequestInterface  $request
     * @param RequestHandlerInterface $handler
     * @return ResponseInterface
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $path = $request->getUri()->getPath();
        if ($request instanceof Request) {
            $path = $request->getPathInfo();
        }

        $path = urldecode($path);
        $route = $this->dispatcher->dispatch($request->getMethod(), $path);

        $status = $route[0];
        if ($status == FastRouteDispatcher::NOT_FOUND) {
            if ($this->notFound instanceof MiddlewareInterface) {
                return $this->notFound->process($request, $handler);
            }

            return $this->response->withStatus(404);
        }

        if ($status == FastRouteDispatcher::METHOD_NOT_ALLOWED) {
            $methods = $route[1];
            return $this->response
                ->withStatus(405)
                ->withHeader('Allow', implode(', ', $methods));
        }

        $routeHandler = $route[1];
        $request = $request->withAttribute('route-request-handler', $routeHandler);
        $request = $request->withAttribute('route-request-path', $path);

        $vars = $route[2];
        foreach ($vars as $name => $value) {
            $request = $request->withAttribute($name, $value);
        }

        return $handler->handle($request);
    }
}