idealogica/route-one

PSR-15 route middleware for advanced middleware routing.

0.1.4 2020-05-24 08:25 UTC

This package is auto-updated.

Last update: 2024-04-24 17:55:11 UTC


README


route-one

The package is in the beta stage

route-one is a PSR-15 compatible middleware aimed to flexibly route a request to another middleware based on HTTP request url path, host, http method, etc. It is built on top of Middleman and Aura.Router packages. It's a good addition to your favorite middleware dispatcher to feel it more likely classical request router. This package also contains a middleware dispatcher that has bunch of useful methods for easy creating route middleware instances.

route-one is very similar to classic controller routers from every modern framework, but it has some more advantages:

  • Standard compliant. You can use any PSR-15 compatible middleware. For example any of these: middlewares/psr15-middlewares.
  • Allows to build multi-dimensional routes and modify response from a group of middleware.
  • It makes your code highly reusable. Any part of the web resource can be bundled as a separate packaged middleware and used in other projects.

Installation

composer require idealogica/route-one:~0.1.0

General usage

// general dispatcher

$dispatcher = DispatcherFactory::createDefault()->createDispatcher();

// page layout middleware

$dispatcher->addMiddleware(
    function (ServerRequestInterface $request, DelegateInterface $next) {
        $response = $next->process($request);
        $content = $response->getBody()->getContents();
        return $response
            ->withBody($this->streamFor('<html><body>' . $content . '</body></html>'))
            ->withHeader('content-type', 'text/html; charset=utf-8');
    }
);

// blog middleware

$dispatcher->addMiddleware(
    function (ServerRequestInterface $request, DelegateInterface $next) {

        // blog middleware dispatcher

        $blogDispatcher = DispatcherFactory::createDefault()->createDispatcher();
        $blogDispatcher->getDefaultRoute()->setHost('www.test.com')->setSecure(false);

        // blog posts list middleware (path based routing)

        $blogDispatcher->addGetRoute('/blog/posts',
            function (ServerRequestInterface $request, DelegateInterface $next) {
                // stop middleware chain execution
                return new Response($this->streamFor('<h1>Posts list</h1><p>Post1</p><p>Post2</p>'));
            }
        )->setName('blog.list');

        // blog single post middleware (path based routing)

        $blogDispatcher->addGetRoute('/blog/posts/{id}',
            function (ServerRequestInterface $request, DelegateInterface $next) {
                $id = (int)$request->getAttribute('1.id'); // prefix for route-one attributes
                // post id is valid
                if ($id === 1) {
                    // stop middleware chain execution
                    return new Response($this->streamFor(sprintf('<h1>Post #%s</h1><p>Example post</p>', $id)));
                }
                // post not found, continue to the next middleware
                return $next->process($request);
            }
        )->setName('blog.post');

        // blog page not found middleware (no routing, executes for each request)

        $blogDispatcher->addMiddleware(
            function (ServerRequestInterface $request, DelegateInterface $next)
            {
                // 404 response
                return new Response($this->streamFor('<h1>Page not found</h1>'), 404);
            }
        );

        return $blogDispatcher->dispatch($request);
    }
);

// dispatching

$response = $dispatcher->dispatch(
    new ServerRequest(
        [],
        [],
        'http://www.test.com/blog/posts/1',
        'GET'
    )
);

(new SapiEmitter())->emit($response);

As you can see you can use callable as middleware. It is not a part of PSR-15 but it can be very helpful for quick prototyping.

Also you can use the route middleware separately with your own dispatcher:

$routeFactory = new RouteFactory(
    new AuraRouteMiddleware($basePath),
    new AuraUriGenerator($basePath)
);
$routeMiddleware = $routeFactory->createGetRoute('/blog/posts', $middlewareToRoute);

For more information on routing rules configuration please refer to Aura.Router routes documentation.

Uri generation

You can use generator to create URIs based or your named routes. Example for the code above:

// route path is '/blog/posts/{id}' for 'blog.post' route
$blogPostUrl = $blogDispatcher->getUriGenerator()->generate('blog.post', ['id' => 100]);
echo($blogPostUrl); // outputs "http://www.test.com/blog/posts/100"

For more information on URIs generation please refer to Aura.Router generator documentation.

License

route-one is licensed under a MIT License.