xp-forge / web
XP 框架的 Web 应用程序
Requires
- php: >=7.0.0
- xp-forge/uri: ^3.0 | ^2.0 | ^1.4
- xp-framework/core: ^12.0 | ^11.0 | ^10.0
- xp-framework/networking: ^10.1 | ^9.3
Requires (Dev)
- xp-framework/test: ^2.0 | ^1.0
- dev-master
- v4.5.0
- v4.4.2
- v4.4.1
- v4.4.0
- v4.3.0
- v4.2.0
- v4.1.1
- v4.1.0
- v4.0.0
- v3.12.0
- v3.11.0
- v3.10.0
- v3.9.0
- v3.8.1
- v3.8.0
- v3.7.0
- v3.6.0
- v3.5.0
- v3.4.1
- v3.4.0
- v3.3.0
- v3.2.0
- v3.1.0
- v3.0.2
- v3.0.1
- v3.0.0
- v2.13.1
- v2.13.0
- v2.12.0
- v2.11.0
- v2.10.0
- v2.9.1
- v2.9.0
- v2.8.0
- v2.7.0
- v2.6.1
- v2.6.0
- v2.5.1
- v2.5.0
- v2.4.0
- v2.3.1
- v2.3.0
- v2.2.0
- v2.1.0
- v2.0.0
- v1.10.2
- v1.10.1
- v1.10.0
- v1.9.0
- v1.8.0
- v1.7.0
- v1.6.4
- v1.6.3
- v1.6.2
- v1.6.1
- v1.6.0
- v1.5.1
- v1.5.0
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.0
- v1.2.0
- v1.1.0
- v1.0.1
- v1.0.0
- v0.14.1
- v0.14.0
- v0.13.0
- v0.12.0
- v0.11.0
- v0.10.0
- v0.9.0
- v0.8.3
- v0.8.2
- v0.8.1
- v0.8.0
- v0.7.0
- v0.6.3
- v0.6.2
- v0.6.1
- v0.6.0
- v0.5.0
- v0.4.0
- v0.3.0
- v0.2.0
- v0.1.0
- dev-feature/pattern-based-routing
- dev-feature/streaming
- dev-feature/flushing
- dev-refactor/migrate-testing
- dev-two
This package is auto-updated.
Last update: 2024-09-15 11:21:50 UTC
README
HTTP 请求的低级功能,包括 xp web 运行器。
示例
use web\Application; class Service extends Application { public function routes() { return [ '/hello' => function($req, $res) { $res->answer(200, 'OK'); $res->send('Hello '.$req->param('name', 'Guest'), 'text/plain'); } ]; } }
使用以下命令运行:
$ xp -supervise web Service @xp.web.srv.Standalone(HTTP @ peer.ServerSocket(Resource id #61 -> tcp://127.0.0.1:8080)) # ...
支持一个开发服务器,速度较慢但允许轻松的编辑/保存/重新加载开发过程。它使用背景中的 PHP 开发服务器。
$ xp -supervise web -m develop Service @xp.web.srv.Develop(HTTP @ `php -S 127.0.0.1:8080 -t /home/example/devel/shorturl`) # ...
现在在 http://localhost:8080/hello 打开网站
服务器模型
以下四个服务器模型(可以通过命令行中的 -m <model>
选择):
- async (自 3.0.0 起为默认值):单线程 Web 服务器。处理器可以在执行长时间操作(如文件上传和下载)时将控制权交还给服务器以服务其他客户端。
- sequential:与上述相同,但在处理完一个客户端的 HTTP 请求处理器后才会处理下一个请求。
- prefork:类似于 Apache,它会为处理 HTTP 请求而 fork 出一定数量的子进程。需要
pcntl
扩展。 - develop:如上所述,建立在 PHP 开发服务器之上。每次请求都会从头开始重新编译应用程序代码和执行应用程序设置,错误和调试输出由 开发控制台 处理。
请求和响应
web.Request
类提供了以下基本功能
use web\Request; $request= ... $request->method(); // The HTTP method, e.g. "GET" $request->uri(); // The request URI, a util.URI instance $request->headers(); // All request headers as a map $request->header($name); // The value of a single header $request->cookies(); // All cookies $request->cookie($name); // The value of a single cookie $request->params(); // All request parameters as a map $request->param($name); // The value of a single parameter
web.Response
类提供了以下基本功能
use web\{Response, Cookie}; $response= ... // Set status code, header(s) and cookie(s) $response->answer($status); $response->header($name, $value); $response->cookie(new Cookie($name, $value)); // Sends body using a given content type $response->send($body, $type); // Transfers an input stream using a given content type. Uses // chunked transfer-encoding. yield from $response->transmit($in, $type); // Same as above, but specifies content length before-hand yield from $response->transmit($in, $type, $size);
两者都提供了一个 stream()
方法来访问底层的输入和输出流。
处理器
处理器(在某些框架中也称为中间件)是一个函数,它接收一个请求和一个响应,并使用上述功能来处理通信。
use web\Handler; $redirect= new class() implements Handler { public function handle($req, $res) { $req->status(302); $req->header('Location', 'https://example.com/'); } };
此库包含 web.handler.FilesFrom
- 一个用于服务文件的处理器。它处理条件请求(带有 If-Modified-Since)以及内容范围请求,并在可用时使用异步功能,请参阅 此处。
过滤器
过滤器围绕处理器,可以在处理器调用前后执行任务。您可以使用请求的 pass()
方法传递值 - 处理器可以使用 value($name)
/ values()
访问这些值。
use web\Filter; use util\profiling\Timer; use util\log\{Logging, LogCategory}; $timer= new class(Logging::all()->toConsole()) implements Filter { private $timer; public function __construct(private LogCategory $cat) { $this->timer= new Timer(); } public function filter($request, $response, $invocation) { $this->timer->start(); try { yield from $invocation->proceed($request, $response); } finally { $this->cat->debugf('%s: %.3f seconds', $request->uri(), $this->timer->elapsedTime()); } } }
通过使用 yield from
,您确保在 finally
块中运行时间测量之前,异步处理器已完全执行。
文件上传
文件上传由请求的 multipart()
方法处理。与 PHP 的工作方式不同,文件上传是流式传输的,处理器从接收到的第一个字节开始运行!
use io\Folder; $uploads= new Folder('...'); $handler= function($req, $res) use($uploads) { if ($multipart= $req->multipart()) { // See https://mdn.org.cn/en-US/docs/Web/HTTP/Status/100 if ('100-continue' === $req->header('Expect')) { $res->hint(100, 'Continue'); } // Transmit files to uploads directory asynchronously $files= []; $bytes= 0; foreach ($multipart->files() as $name => $file) { $files[]= $name; $bytes+= yield from $file->transmit($uploads); } // Do something with files and bytes... } };
早期提示
一个实验性的状态码,可以通过它将标题提前发送到客户端,以便它能够进行优化,例如预加载脚本和样式表。
$handler= function($req, $res) { $res->header('Link', [ '</main.css>; rel=preload; as=style', '</script.js>; rel=preload; as=script' ]); $res->hint(103); // Do some processing here to render $html $html= ... $res->answer(200, 'OK'); $res->send($html, 'text/html; charset=utf-8'); }
请参阅 https://evertpot.com/http/103-early-hints
内部重定向
除了由 3XX 状态码触发的外部重定向之外,还可以使用 dispatch()
方法在内部重定向请求。这的好处是不需要客户端执行额外的请求。
use web\Application; class Site extends Application { public function routes() { return [ '/home' => function($req, $res) { // Home page }, '/' => function($req, $res) { // Routes are re-evaluated as if user had called /home return $req->dispatch('/home'); }, ]; } }
日志记录
默认情况下,日志会输出到标准输出,在从 xp web
命令调用的控制台可见。可以通过以下命令行进行影响:
-l server.log
:将日志写入文件 server.log,如果需要则创建它-l -
:将日志写入标准输出-l - -l server.log
:将日志写入上述两个位置
在应用程序内部,可以获得更精细的控制以及与 日志库 的集成,请参阅 此处。
性能
因为在使用生产服务器时,Web应用程序的代码仅编译一次,所以我们实现了闪电般的请求/响应往返时间
另请参阅
此库提供了非常基础的功能。要创建Web前端或REST API,请查看以下基于此构建的库