哺乳动物/http-server

🐙 多 vhost HTTP 服务器

安装量: 7,771

依赖者: 0

建议者: 0

安全: 0

星标: 2

关注者: 2

分支: 0

开放问题: 9

类型:composer-plugin

dev-master 2023-01-14 18:38 UTC

README

time docker run --rm -w `pwd` -v `pwd`:`pwd` -p 9666:9666  -it wyrihaximusnet/php:7.4-zts-alpine3.11 php ./vendor/bin/mammatus

HTTP 服务器命令

Build Status Latest Stable Version Total Downloads Code Coverage License PHP 7 ready

安装

要通过 Composer 安装,请使用以下命令,它将自动检测最新版本并将其绑定到 ^

composer require reactive-apps/command-http-server

控制器

控制器分为静态控制器和实例化控制器两种。

静态控制器

当您的控制器没有任何依赖时,建议使用静态控制器,例如用于 updown.io 健康检查的此 ping 控制器。 注意: /ping 不是 updown 标准,但它是我在我的应用程序中进行健康检查的个人标准 此控制器只有一个方法、一个路由和无依赖项

<?php declare(strict_types=1);

namespace App\Controller;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use ReactiveApps\Command\HttpServer\Annotations\Method;
use ReactiveApps\Command\HttpServer\Annotations\Routes;
use RingCentral\Psr7\Response;

final class Ping
{
    /**
     * @Method("GET")
     * @Routes("/ping")
     *
     * @param  ServerRequestInterface $request
     * @return ResponseInterface
     */
    public static function ping(ServerRequestInterface $request): ResponseInterface
    {
        return new Response(
            200,
            ['Content-Type' => 'text/plain'],
            'pong'
        );
    }
}

实例化控制器

另一方面,实例化控制器将被实例化并保留以处理未来的更多请求,因此它们可以注入依赖项。以下示例是一个注入事件循环以等待随机秒数后返回响应的控制器。它还使用协程使代码更具可读性

<?php declare(strict_types=1);

namespace App\Controller;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use React\EventLoop\LoopInterface;
use ReactiveApps\Command\HttpServer\Annotations\Method;
use ReactiveApps\Command\HttpServer\Annotations\Routes;
use ReactiveApps\Command\HttpServer\Annotations\Template;
use ReactiveApps\Command\HttpServer\TemplateResponse;
use WyriHaximus\Annotations\Coroutine;
use function WyriHaximus\React\timedPromise;

/**
 * @Coroutine())
 */
final class Root
{
    /** @var LoopInterface */
    private $loop;

    /** @var int */
    private $time;

    public function __construct(LoopInterface $loop)
    {
        $this->loop = $loop;
        $this->time = \time();
    }

    /**
     * @Method("GET")
     * @Routes("/")
     * @Template("root")
     *
     * @param  ServerRequestInterface $request
     * @return ResponseInterface
     */
    public function root(ServerRequestInterface $request)
    {
        $start = \time();

        yield timedPromise($this->loop, \random_int(1, 5));

        return (new TemplateResponse(
            200,
            ['Content-Type' => 'text/plain']
        ))->withTemplateData([
            'uptime' => (\time() - $this->time),
            'took' => (\time() - $start),
        ]);
    }
}

路由

路由是通过处理路由的方法上的注解来完成的。每个方法可以处理多个路由,但建议仅映射适合该方法的路由。

例如,以下注解将映射当前方法到 /注意:所有路由都必须以 / 前缀):@Routes("/")

多路由注解的语法略有不同,在以下示例中,/old/new 都将由同一个方法处理

@Routes({
    "/old",
    "/new"
})

路由的底层引擎是 nikic/fast-route,这也使得像这样的复杂路由成为可能

@Route("/{map:(?:wow_cata_draenor|wow_cata_land|wow_cata_underwater|wow_legion_azeroth|wow_battle_for_azeroth|wow_cata_elemental_plane|wow_cata_twisting_nether|wow_comp_wotlk)}/{zoom:1|2|3|4|5|6|7|8|9|10}/{width:[0-9]{1,5}}/{height:[0-9]{1,5}}/{center:[a-zA-Z0-9\`\-\~\_\@\%]{1,35}}{blips:/blip\_center|/[a-zA-Z0-9\`\-\~\_\@\%\[\]]{3,}.+|}.{quality:png|hq.jpg|lq.jpg}")

不同的路由组件如 mapcenter 可以通过请求对象使用

$request->getAttribute('center');

模板

路由可以在完成时渲染模板,它需要一个注解,并以包含该模板所需数据的 TemplateResponse 返回/解决。例如

/**
 * @Template("root")
 */
public function root(ServerRequestInterface $request)
{
    return (new TemplateResponse(
        200,
        ['Content-Type' => 'text/plain']
    ))->withTemplateData([
        'beer' => 'Allmouth', // https://untappd.com/user/WyriHaximus/checkin/745226210
    ]);
}

请求中的阻塞操作

虽然我们旨在构建一个完全非阻塞的应用程序,但我们无法回避这样一个事实,即我们的应用程序中可能会有部分会阻塞循环。对于这些情况,有两种方法可以处理这些情况

  • 子进程(慢,为每个工作进程启动完整的 PHP 进程以处理请求)
  • 线程(快,使用线程来完成工作,需要 ZTS 版本的 PHP)

子进程

适用于大多数系统,但需要每个工作进程一个完整的 PHP 进程。启动可能较慢,并且与子进程的通信通过套接字进行。将 @ChildProcess 注解添加到处理该特定操作的子进程中。

线程

仅适用于 ZTS PHP 构建,但启动几乎瞬间完成,通信直接在内存中,因此永远不会离开应用程序服务器。将 @Thread 注解添加到处理该特定操作的线程中。

注解

  • @ChildProcess - 在子进程中运行控制器操作
  • @Coroutine - 在协程中运行控制器操作
  • @Method - 允许的 HTTP 方法(GET、POST、PATCH 等)
  • @Routes - 使用给定方法的路由
  • @Template - 当使用 TemplateResponse 时使用的模板
  • @Thread - 在线程中运行控制器操作(首选于使用子进程)

选项

  • http-server.address - 监听用的 IP 地址 + 端口,例如:0.0.0.0:8080
  • http-server.hsts - 是否设置 HSTS 头部
  • http-server.public - 公共的 web 根目录,注意这里只能放置允许所有人查看的文件
  • http-server.public.preload.cache - 用于存储预加载的 web 根目录文件的自定义缓存,默认存储在内存中
  • http-server.middleware.prefix - 在 accesslog 和 web 根目录服务中间件之前添加的 react/http 中间件数组
  • http-server.middleware.suffix - 在 accesslog 和 web 根目录服务中间件之后、路由中间件和请求处理器之前添加的 react/http 中间件数组
  • http-server.pool.ttl - 子进程等待下一个任务的 TTL
  • http-server.pool.min - 最小子进程数
  • http-server.pool.max - 最大子进程数
  • http-server.rewrites - 在内部重新编写请求路径,从一条路径到另一条路径,对访客不可见

许可证

MIT 许可证 (MIT)

版权所有 (c) 2019 Cees-Jan Kiewiet

特此授予任何获得此软件及其相关文档副本(以下简称“软件”)的个人免费使用软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本,以及允许获得软件的个人进行此类操作,前提是遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“原样”提供,不提供任何明示或暗示的保证,包括但不限于对适销性、适用于特定目的和不受侵犯的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任承担责任,无论此类责任基于合同、侵权或其他原因,以及与软件、使用或以其他方式处理软件相关的任何索赔、损害或其他责任。