http-server-router
AMPHP is a collection of event-driven libraries for PHP designed with fibers and concurrency in mind.
This package provides a routing RequestHandler
for amphp/http-server
based on the request path and method using FastRoute., (*1)
Installation
This package can be installed as a Composer dependency.
You should specify amphp/http-server
as a separate dependency., (*2)
composer require amphp/http-server-router
Usage
Router
implements RequestHandler
, which is used by an HttpServer
to handle incoming requests. Incoming requests are routed by Router
to other RequestHandler
s based on the request path., (*3)
Routes can be defined using the addRoute($method, $uri, $requestHandler)
method., (*4)
public function addRoute(
string $method,
string $uri,
RequestHandler $requestHandler
): void
Matched route arguments are available in the request attributes under the Amp\Http\Server\Router
key as an associative array.
Please read the FastRoute documentation on how to define placeholders., (*5)
Middleware
You can stack all routes with a common set of middleware using addMiddleware($middleware)
.
Each middleware is called in the order of the addMiddleware()
calls.
The router will not invoke any middleware for the fallback handler., (*6)
public function addMiddleware(Middleware $middleware): void
Note
Per-route middleware can be added by using Amp\Http\Server\Middleware\stackMiddleware()
before passing the RequestHandler
to addRoute()
., (*7)
Fallback
If no routes match a request path, you can specify another instance of RequestHandler
which will handle any unmatched routes. If no fallback handler is provided, a 404 response will be returned using the instance of ErrorHandler
provided to the Router
constructor., (*8)
public function setFallback(RequestHandler $requestHandler): void
Note
Middleware defined by Router::addMiddleware()
will not be invoked when a request is forwarded to fallback handler. Use Amp\Http\Server\Middleware\stackMiddleware()
to wrap the fallback request handler with any middlewares needed first., (*9)
Example
use Amp\Http\HttpStatus;
use Amp\Http\Server\DefaultErrorHandler;
use Amp\Http\Server\Request;
use Amp\Http\Server\RequestHandler\ClosureRequestHandler;
use Amp\Http\Server\Response;
use Amp\Http\Server\Router;
use Amp\Http\Server\SocketHttpServer;
// $logger is an instance of a PSR-3 logger.
$server = SocketHttpServer::createForDirectAccess($logger);
$errorHandler = new DefaultErrorHandler();
$router = new Router($server, $logger, $errorHandler);
$router->addRoute('GET', '/', new ClosureRequestHandler(
function () {
return new Response(
status: HttpStatus::OK,
headers: ['content-type' => 'text/plain'],
body: 'Hello, world!',
);
},
));
$router->addRoute('GET', '/{name}', new ClosureRequestHandler(
function (Request $request) {
$args = $request->getAttribute(Router::class);
return new Response(
status: HttpStatus::OK,
headers: ['content-type' => 'text/plain'],
body: "Hello, {$args['name']}!",
);
},
));
$server->expose('0.0.0.0:1337');
$server->start($router, $errorHandler);
// Serve requests until SIGINT or SIGTERM is received by the process.
Amp\trapSignal([SIGINT, SIGTERM]);
$server->stop();
A full example is found in examples/hello-world.php
., (*10)
php examples/hello-world.php
Limitations
The Router
will decode the URI path before matching.
This will also decode any forward slashes (/
), which might result in unexpected matching for URIs with encoded slashes.
FastRoute placeholders match path segments by default, which are separated by slashes.
That means a route like /token/{token}
won't match if the token contains an encoded slash.
You can work around this limitation by using a custom regular expression for the placeholder like /token/{token:.+}
., (*11)
Security
If you discover any security related issues, please use the private security issue reporter instead of using the public issue tracker., (*12)
License
The MIT License (MIT). Please see LICENSE for more information., (*13)