Middleware to execute request handlers discovered by a router

Overview

middlewares/request-handler

Latest Version on Packagist Software License Testing Total Downloads

Middleware to execute request handlers discovered by a router.

Requirements

Installation

This package is installable and autoloadable via Composer as middlewares/request-handler.

composer require middlewares/request-handler

You may also want to install any route middleware like middlewares/fast-route or middlewares/aura-router for routing.

Purpose

There are two completely separate steps when it comes to route handling:

  1. Determining if the request is valid and can be resolved by the application.
  2. Handling the request inside the application.

The first step usually resolves into a route callback, while the product of the second one is usually the result of executing that callback.

Multiple things that can happen between the first and second steps: input validation, authentication, authorization, etc. and in some scenarios we may not want to continue processing the request (e.g. auth, accessing DB resources, etc.) if that would ultimately fail to resolve e.g. procuding an HTTP 400 error.

Splitting routing from request handling allows us to use any middleware between these two steps. It also makes the request-handler middleware able to be used with any routing component.

Example

A routing middleware needs to be called before the request can be handled. In this example, we will use fast-route middleware.

// Create the routing dispatcher
$fastRouteDispatcher = FastRoute\simpleDispatcher(function (FastRoute\RouteCollector $r) {
    $r->get('/hello/{name}', HelloWorldController::class);
});

$dispatcher = new Dispatcher([
    new Middlewares\FastRoute($fastRouteDispatcher),
    // ...
    new Middlewares\RequestHandler(),
]);

$response = $dispatcher->dispatch(new ServerRequest('/hello/world'));

When the request handler is invoked, it expects a request attribute to be defined that contains a reference to the handler. The handler must be a string, a callable or an object implementing MiddlewareInterface or RequestHandlerInterface. If it's a string, a ContainerInterface will be used to resolve it and get the MiddlewareInterface or RequestHandlerInterface to use. If it's a callable, it will be converted automatically to MiddlewareInterface using the Middlewares\Utils\CallableHandler

// Use a PSR-11 container to create the intances of the request handlers
$container = new RequestHandlerContainer();

$dispatcher = new Dispatcher([
    // ...
    new Middlewares\RequestHandler($container),
]);

Usage

Define the container used to resolve the handlers if they are provided as string (or an array with 2 strings). By default will use Middlewares\Utils\RequestHandlerContainer.

// Use the default PSR-11 container to create the intances of the request handlers
$handler = new Middlewares\RequestHandler();

// Use a custom PSR-11 container
$container = new RequestHandlerContainer();

$handler = new Middlewares\RequestHandler($container);

handlerAttribute

Configures the attribute name used to get the handler reference in the server request. The default is request-handler.

Dispatcher::run([
    (new Middlewares\RequestHandler())->handlerAttribute('route'),
]);

continueOnEmpty

If the server request attribute is empty or does not exists, an exception is throwed. This function changes this behavior to continue with the next middleware.

Dispatcher::run([
    //Try this, and if it's empty, continue
    (new Middlewares\RequestHandler())->continueOnEmpty(),

    //So we can try that
    (new Middlewares\RequestHandler())->handlerAttribute('other'),
]);

Please see CHANGELOG for more information about recent changes and CONTRIBUTING for contributing details.

The MIT License (MIT). Please see LICENSE for more information.

Comments
  • Remove usage of CallableHandler?

    Remove usage of CallableHandler?

    Given that HTTP factories exist, why do we need to use CallableHandler to execute the handler Why not simplify the execution path and force the handler to return a ResponseInterface?

    question 
    opened by shadowhand 7
  • Make it possible to extend RequestHandler

    Make it possible to extend RequestHandler

    Hey, I wanted to extend RequestHandler but wasn't able to access $this->container or $this->handlerAttribute because they're private. This PR degrades the properties to protected so that we can access them if we need to.

    opened by brayniverse 5
  • composer: allow php ^8.0

    composer: allow php ^8.0

    Should I send also migration from Travis to GitHub actions? Since Travis is ultra-slow these days and obviously does not have PHP 8.0 ready, GitHub actions are far better nowadays.

    opened by solcik 2
  • Why not delegate to $handler

    Why not delegate to $handler

    When no valid attribute is present, the middleware could keep delegating after all... Or is there just no sensible use-case?

    Asking because middlewares/base-path-router#3 makes me imagine a situation where the router has dynamic prefixes, but no default handler, it could just delegate to its own handler. Using request-handler as that delegate would then lead to a situation where request-handler would need a fallthrough. Isn't that the best place for the defaultHandler? After all, the router isn't useful without request-handler anyway, so it could just rely on the latter for the default handler.

    opened by franzliedke 2
  • Closure/callable from router isn't supported ?

    Closure/callable from router isn't supported ?

    Hi,

    I looked at the fastroute & aurarouter middleware and they both claim you can add a handler as a closure, callable, controller...Etc :

    FastRoute allows anything to be defined as the router handler (a closure, callback, action object, controller class, etc). The middleware will store this handler in a request attribute.

    But in your middleware requestHandler, the handler retrieved in the request can only be a typeof middlewareinterface or requesthandlerinterface or a string (a key to search in the container), but if the handler is of type : closure or callable, then this middleware will not be working (no handler execution).

    you explain me why this possibility is not present ? thank you.

    Keep up the good work.

    opened by ncou 2
  • Support psr/container 2

    Support psr/container 2

    Hi, this adds support for psr/container ^2.0. It merely adds a return type to one of the ContainerInterface methods, so there is no breaking change for this package. Also, since psr/container is a hard dependency now, I've removed it from suggest where it seems redundant.

    opened by jiripudil 1
  • PHPUnit: Prophecy - failing build

    PHPUnit: Prophecy - failing build

    @oscarotero the build is failing just because of the new dependency phpspec/prophecy-phpunit, which I added - because of new PHPUnit deprecated calling prophesize and suggests to install this package and use Trait from it.

    https://github.com/middlewares/request-handler/blob/master/tests/RequestHandlerTest.php#L23 https://github.com/middlewares/request-handler/blob/master/tests/RequestHandlerTest.php#L82

    opened by solcik 1
  • Route specific middleware

    Route specific middleware

    I've managed to use the request-handler combined with aura-router with a single router handler.

    Am trying to implement route specific middleware, as opposed to the 'global' application middleware.

    $routerContainer = new RouterContainer();
    $map = $routerContainer->getMap();
    
    // Works fine...
    $map->get('index', '/', 'App\Http\Controllers\HomeController::index');
    
    // Error: Invalid request handler: array
    $map->get('index', '/', [
        new SampleRouteMiddleware(),
        'App\Http\Controllers\HomeController::index'
    ]);
    
    $request = ServerRequestFactory::fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
    
    $requestContainer = new RequestHandlerContainer();
    
    $dispatcher = new Dispatcher([
        new SampleAppMiddleware(),
        new AuraRouter($routerContainer),
        new RequestHandler($requestContainer),
    ]);
    
    $response = $dispatcher->dispatch($request);
    
    opened by mtvbrianking 1
Owner
Middlewares
PSR-15 HTTP Middlewares
Middlewares
Yii-specific middleware

Yii Middleware The package ... Requirements PHP 8.0 or higher. Installation The package could be installed with composer: composer require yiisoft/yii

Yii Software 9 Nov 4, 2022
This repository contains a library of optional middleware for your Slim Framework application

Slim Framework Middleware This repository contains a library of optional middleware for your Slim Framework application. How to Install Update your co

Slim Framework 47 Nov 7, 2022
Juliangut Slim Framework Doctrine handler middleware

Juliangut Slim Framework Doctrine handler middleware Doctrine handler middleware for Slim Framework. Slim3 version Doctrine integration service for Sl

Julián Gutiérrez 6 Mar 23, 2021
This Slim Framework middleware will compile LESS CSS files on-the-fly using the Assetic library

This Slim Framework middleware will compile LESS CSS files on-the-fly using the Assetic library. It supports minification and caching, also via Asseti

Gerard Sychay 22 Mar 31, 2020
Northwoods Lazy Middleware

Northwoods Lazy Middleware Lazy loading for PSR-15 middleware and request handlers that supports "just in time" instantiation using a PSR-11 container

Northwoods Technology 4 Aug 10, 2019
Access control middleware for Slim framework

Slim Access Access control middleware for Slim framework. Supported formats IPv4 and IPv6 addresses CIDR notation all keyword Installation composer re

Alexandre Bouvier 7 Oct 22, 2019
Redis cache middleware for Slim framework

RedisCache Redis cache middleware for Slim framework. Installation composer require abouvier/slim-redis-cache Usage Cache every successful HTTP respo

Alexandre Bouvier 16 Sep 20, 2021
Slim Framework HTTP cache middleware and service provider

Slim Framework HTTP Cache This repository contains a Slim Framework HTTP cache middleware and service provider. Install Via Composer $ composer requir

Slim Framework 107 Dec 15, 2022
CORS Middleware for PHP Slim Framework

CorsSlim Cross-origin resource sharing (CORS) Middleware for PHP Slim Framework. Usage Composer Autoloader Install with Composer Update your composer.

Palani Kumanan 92 Nov 30, 2021
PHP slim framework middleware to minify HTML output

slim-minify Slim middleware to minify HTML output generated by the slim PHP framework. It removes whitespaces, empty lines, tabs beetween html-tags an

Christian Klisch 35 Oct 31, 2021
Slim Framework CSRF protection middleware

Slim Framework CSRF Protection This repository contains a Slim Framework CSRF protection PSR-15 middleware. CSRF protection applies to all unsafe HTTP

Slim Framework 302 Dec 11, 2022
Mediator - CQRS Symfony bundle. Auto Command/Query routing to corresponding handlers.

Installation $ composer require whsv26/mediator Bundle configuration // config/packages/mediator.php return static function (MediatorConfig $config)

Alexander Sv. 6 Aug 31, 2022
Execute time consuming tasks as late as possible in a request

Procrastinator for PHP: do stuff later A few classes to help you executing complicated tasks (like sending mails) later. Example using fastcgi_finish_

Lars Strojny 62 Apr 29, 2021
PHP Router class - A simple Rails inspired PHP router class.

PHP Router class A simple Rails inspired PHP router class. Usage of different HTTP Methods REST / Resourceful routing Reversed routing using named rou

Danny van Kooten 565 Jan 8, 2023
Fast request router for PHP

FastRoute - Fast request router for PHP This library provides a fast implementation of a regular expression based router. Blog post explaining how the

Nikita Popov 4.7k Dec 23, 2022
This Package helps you in laravel application to log all desired activity for each request from request entry point to generate response at a single snapshot.

Laravel Scenario Logger This Package helps you in laravel application to log all desired activity for each request from request entry point to generat

Mehrdad Mahdian 6 Sep 27, 2021
Csrf Component provides Cross Site Request Forgery protection by comparing provided token with session token to ensure request validity.

Csrf Component Csrf Component provides Cross Site Request Forgery protection by comparing provided token with session token to ensure request validity

ATOMASTIC 3 Mar 12, 2022
HTTP Requestor: Package for a client request that supports you to make an external service request easily and with fast usage.

HttpRequestor from Patienceman HTTP Requestor: Package for a client request that supports you to make an external service request easily and with fast

Manirabona Patience 2 Aug 26, 2022
Middleware to generate access logs for each request using the Apache's access log format

Middleware to generate access logs for each request using the Apache's access log format. This middleware requires a Psr log implementation, for example monolog.

Middlewares 20 Jun 23, 2022
PSR-7 middleware foundation for building and dispatching middleware pipelines

laminas-stratigility From "Strata", Latin for "layer", and "agility". This package supersedes and replaces phly/conduit. Stratigility is a port of Sen

Laminas Project 47 Dec 22, 2022