狼群/router

简单路由与分发器实现。

v1.4.2 2024-07-09 21:57 UTC

This package is auto-updated.

Last update: 2024-09-09 22:21:09 UTC


README

可用方法

  • ANY 对所有方法可用
  • CLI 用于命令提示符
  • GET 方法请求指定资源的表示。
  • HEAD 方法请求与GET请求相同,但不包含响应体。
  • POST 方法向指定资源提交实体,通常会导致服务器状态改变或副作用。
  • PUT 方法用请求有效载荷替换目标资源的所有当前表示。
  • DELETE 方法删除指定的资源。
  • CONNECT 方法为指定的目标资源建立到服务器的隧道。
  • OPTIONS 方法描述目标资源的通信选项。
  • TRACE 方法在目标资源路径上执行消息回环测试。
  • PATCH 方法对资源应用部分修改。

路径变体和中间件

<?php declare(strict_types=1);

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

require __DIR__ . '/vendor/autoload.php';

// composer require vulpes/container
$container = new Container\Container;

/** @var Psr\Container\ContainerInterface $container */
$dispatcher = new Http\Dispatcher(container: $container);

// add anonymous Middleware globally as object
$dispatcher->addMiddleware(new class implements MiddlewareInterface {
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // TODO before
        $response = $handler->handle($request);
        // TODO after
        return $response;
    }
});

// add Middleware globally as string (the ContainerInterface will create it's instance)
$dispatcher->addMiddleware(Middleware\AnotherMiddleware::class);

// You can also insert middleware at the very beginning of the line, for example for error handling,
// to catch the Http\Exception\NotFoundException thrown by the router
$dispatcher->appendMiddleware(Middleware\ErrorHandlerMiddleware::class);

$dispatcher
    // You can set prefix for paths via groups
    ->addGroup(name: 'rest-v1', path: 'api/v1')
        ->addMiddleware(Http\Middleware\JsonMiddleware::class)
        ->appendMiddleware('id-for-a-middleware-1')
        
    // You can use more groups for one simple path
    ->addGroup(name: 'rest-v2', path: 'api/v2')
        ->addMiddleware(Http\Middleware\JsonMiddleware::class)
        ->appendMiddleware('id-for-a-middleware-2')
        
    // You can use groups for simple authentication layers
    ->addGroup(name: 'admin')
        ->appendMiddleware('just-a-container-id-for-an-authentication-middleware')
        
    // add command line endpoint MyController->index()
    ->addPath(method: 'GET', path: '/', requestHandler: MyController::class . '::index')
        // add Middleware locally to current Path as string (classname), you can use object as well
        ->addMiddleware(Http\Middleware\JsonMiddleware::class)

    // add command line endpoint, MyController->service(int $thread)
    ->addPath(method: 'CLI', path: '/service/{thread:int}', requestHandler: MyController::class . '::service')

    // add command line endpoint, MyController->create()
    ->addPath(
            method: 'POST',
            // because of groups the full path will be: "/api/v1/entity/create", and "/api/v2/entity/create"
            path: '/entity/create',
            requestHandler: MyController::class . '::create', 
            groups: 'rest-v1', 'rest-v2'
    )
    // add Middleware locally to current path as string (classname), you can use object as well
    ->addMiddleware(Middleware\MyMiddleware::class)
    ->appendMiddleware(Middleware\AnotherErrorMiddleware::class)
    
    // The above middlewares will behave according to the pattern below (with global middlewares), with rest-v1 group
    // AnotherErrorMiddleware  :before
    // id-for-a-middleware-1   :before
    // ErrorHandlerMiddleware  :before
    // anonymous               :before
    // AnotherMiddleware       :before
    // JsonMiddleware          :before
    // MyMiddleware            :before
    // MyController->create()          - throws Throwable, everything from controller
    // MyMiddleware            :after
    // JsonMiddleware          :after
    // AnotherMiddleware       :after
    // anonymous               :after
    // ErrorHandlerMiddleware  :after - You can catch RouterInterface's NotFoundException here
    // id-for-a-middleware-1   :after
    // AnotherErrorMiddleware  :after - ... or here

    // You can use RequestHandler (RequestHandlerInterface) as Controller too
    ->addPath(method: 'POST', path: '/entity/create', requestHandler: MyRequestHandler::class);

// composer require vulpes/http
$serverRequest = (new Http\Factory\ServerRequestFactory)->createServerRequestFromGlobals();

try {
    print $dispatcher->handle($serverRequest)/* ResponseInterface */->getBody();
} catch (Throwable $e) {
    print $e;
}