hebbinkpro/pmmp-webserver

A HTTP/1.1 webserver Virion for PocketMine plugins

0.4.1 2024-03-20 10:54 UTC

This package is auto-updated.

Last update: 2024-09-20 14:36:43 UTC


README

一个用于 PocketMine-MP 插件创建简单 HTTP/1.1 网络服务器的版本。

插件

  • 该病毒体用于我的 Dynmap 类似插件 PocketMap。您可以在这里找到插件

如何安装

  • Poggit CI 下载最新版本的 phar 构建
  • 或直接使用 composer 安装:composer require hebbinkpro/pmmp-webserver

如何使用

创建网络服务器

为了创建网络服务器,您必须注册 WebServer 并创建一个新的 WebServer 实例以启动服务器。

<?php

use Hebbinkpro\WebServer\WebServer;
use Hebbinkpro\WebServer\http\server\HttpServerInfo;

class YourPlugin extends \pocketmine\plugin\PluginBase {
    
    protected function onEnable() : void{
        // ...
        
        $serverInfo = new HttpServerInfo("0.0.0.0", 80)
        // Create a new server on the address and port
        $webServer = new WebServer($this, $serverInfo);
        
        // after starting the server, the site will be available at http://127.0.0.1:80
        $webServer->start();
    }
}

请注意,如果您想从您的 localhost 或本地网络之外访问服务器,您可能需要进行端口转发,否则它将无法对外部网络可用!

路由

路由用于让您的网络服务器能够执行操作。通过创建一个 Route,您可以使您的网络服务器监听不同的路径并对它们做出响应。

路由器

路由器用于注册所有路由。路由器还将处理所有传入请求并确保它们由正确的 Route 处理。
您可以通过调用以下方式访问您的 WebServer 的路由器:

$router = $webServer->getServerInfo()->getRouter();

Route

路由用于对传入的 Web 请求执行操作。

use Hebbinkpro\WebServer\http\HttpMethod;
use Hebbinkpro\WebServer\http\message\HttpRequest;
use Hebbinkpro\WebServer\http\message\HttpResponse;
use Hebbinkpro\WebServer\route\Route;
{
    // the method can be any value in the HttpMethod class.
    // these methods represent HTTP request methods and makes the route listen to a specific type of request.
    // if you want to listen to all requests, you can use HttpMethod::ANY (or "*").
    $method = HttpMethod::GET;
    
    // the specific path the route will listen to,
    // you can find out more about the paths below
    $path = "/";
    
    // the action is the part that will execute once a client makes a request to the given method AND path.
    // the HttpRequest inside the function is the request the client made to the web server
    // the HttpResponse is the response the server will send back to the client after the function returns.
    $action = function (HttpRequest $request, HttpResponse $response) {
        // This will send the string "Hello World" back to the client.
        $response->text("Hello World");
        
        // the text function is one of the many simplified versions of the 'send' function
        // by using the send function, you can input a string and set the HTTP content type
        // the example below will send the string "<h1>Hello World</h1>" to the client and the client will see it as an HTML file.
        $response->send("<h1>Hello World</h1>", "text/html");
        
        // You can also send complete files using Response.
        // this makes it really easy to send any kind of file
        $response->sendFile("/path/to/your/file");
        
        // but remember, you can only use ONE response action at any time
        // each new response action will OVERWRITE the previous.
        // So if you want to send multiple things in a single response,
        // consider splitting it in multiple files, or sending everything in 1 response
    }
    
    // now we construct the Route with our given method, path and action.
    $route = new Route($method, $path, $action);
}
路由动作

路由动作是在将新请求发送到正确路径时执行的任务。动作的语法是

function (HttpRequest $request, HttpResponse $response, mixed ...$params) {
    // your code
}
  • $request 是传入的请求
  • $response 是将返回给客户端的响应
  • ...$params 是包含所有给定参数的数组。参数在新的 Route 的末尾给出。
    $route = new \Hebbinkpro\WebServer\route\Route($method, $action, ...$params);

您可以添加任意多的参数,如果您只想有一个参数,您可以使用 new Route($method, $path, $action, $param1),但如果您想有多个,您可以将它们添加到第一个参数之后。new Route($method, $path, $action, $param1, $param2, $param3)。不添加参数也是选项之一,new Route($method, $path, $action)
要在动作中使用 ...$params 变量,您可以使用它作为一个数组,所以 $params[0] 将返回第一个参数,而 $params[1] 将给出第二个,依此类推。
不要在动作函数内部放置任何使用主线程的代码。动作必须是 ThreadSafe 的,因此只有不依赖于 PocketMine 线程的东西才能工作。如果您想使用不扩展 pmmp\thread\ThreadSafe 的类,您可以使用 serialize(...) 对参数进行序列化,并在动作函数内部使用 unserialize(...) _

创建 HTTP 请求路由的路由器方法

对于最常用的方法,在 Router 实例内部有函数。这些函数使得您不必为每个新创建的 Route 输入 HTTP 方法
Router 中可用的方法函数有

  • GET,仅监听 GET 请求的路由 - Router->get($path, $action, ...$params)
  • POST,仅监听 POST 请求的路由 - Router->post($path, $action, ...$params)
  • HEAD,仅监听 HEAD 请求的路由 - Router->head($path, $action, ...$params)
  • PUT,仅监听 PUT 请求的路由 - Router->put($path, $action, ...$params)
  • DELETE,仅监听DELETE请求的路由 - Router->delete($path, $action, ...$params)
  • USE(也称为ANY或*,在Hebbinkpro\WebServer\http\HttpMethod中),一个监听所有HTTP方法的路由 - Router->all($path, $action, ...$params)

关于HTTP请求方法的更多信息,请参阅这里

路由函数内部的路径和操作参数与Router中的相同。

其他路由类型

Router中,除了默认的Route实现外,您还可以使用以下三种类型的路由:

  • Route - 一个基本路由,允许您为路径创建自己的响应
  • FileRoute - 一个发送文件作为响应的路由
  • RouterRoute - 一个作为Router功能运行的路由,但仅针对指定的路径
  • StaticRoute - 一个允许您共享完整文件夹内容而不为每个不同的路径创建Route的路由
  • 您不仅限于这些路由,还可以创建自己的路由。唯一的要求是您的自定义路由必须扩展(是\Hebbinkpro\WebServer\route\Route的子类)。您可以使用以下方式将Route实例添加到Router中:
$router->addRoute($route)

但是,Router中也有函数可以轻松添加FileRouteRouterRouteStaticRoute

FileRoute
$file = "path/to/your/file";
$default = "File not found";

// add the file route, $default is optional
$router->getFile($path, $file, $default);
RouterRoute
use Hebbinkpro\WebServer\router\Router;

$childRouter = new Router();
// add here the stuff you want to the child router
// this is the same as for a default router
// ...

// add the router route with the path and the newly created child router
$router->route($path, $childRouter);
Static Route
// define the folder you want to use for the static route by using its path
$folder = "/path/to/the/folder";

// add the static route with the path of the route and the folder path
$router->getStatic($path, $folder)

路径

路由路径是URL中的路径,这些路径非常重要,因为它们包含客户端想要查看的页面信息。但是,为了确保客户端看到正确的页面,此页面的路径必须有一个Route。这就是为什么对于您创建的每个Route,如果它使用Router中的函数或创建新的Route实例,您必须提供一个有效的路径,否则客户端无法找到或请求您的页面。

默认路径

路径不过是地址后面的第一个/之后到末尾或?之间的所有内容。

前缀

有时您需要一个监听所有以/foo开头的请求的路由,例如/foo/bar/foo/bar/etc
我们可以通过在路径末尾添加/*来实现这一点。

参数

有时您需要一个前缀,但还需要一个后缀。为了实现这一点,我们引入了参数。参数是路径的一部分,可以是任何类型的字符串,因此路径/:var/a将监听/foo/a,但也将监听/bar/a。更好的是,您还可以使用HttpRequest->getPathParams()请求HttpRequest内的所有变量,这将返回一个数组,其中以参数名称为键,以路径中的值设置为值。

查询

路径的查询是路径中?后面的所有内容,例如/?foo=bar。可以使用&符号在两个值之间使用多个查询。单个查询表示为<name>=<value>
要请求所有查询,请使用HttpURI->getQuery(),或要请求单个值,请使用HttpURI->getQueryParam($name)

HTTPS

从v1.0.0版本开始,Web服务器也支持SSL证书,这使得运行一个比HTTP更安全的HTTPS服务器成为可能。
要启用Web服务器的HTTPS,您必须在启动Web服务器之前将SslSettings添加到HttpServerInfo中。这可以通过多种方式完成。

  1. 让Web服务器通过调用$webServer->detectSSL()检测插件数据cert文件夹中的SSL证书。
  2. 通过调用$ssl = new SslSettings(...)创建一个新的SslSettings对象,并将其添加到HttpServerInfo中:new HttpServerInfo(..., $ssl)或者通过调用$serverInfo->setSSL($ssl)。如果您在启动服务器后添加SSL设置,HTTPS将不会应用,并且您的服务器将作为一个普通的HTTP服务器运行。

致谢

  • 该病毒利用Laravel\SerializableClosure来共享在主线程上通过Router给出的动作函数,以与http服务器线程共享。