xp-forge/web
Composer 安装命令:
composer require xp-forge/web
包简介
Web applications for the XP Framework
README 文档
README
Low-level functionality for serving HTTP requests, including the xp web runner.
Example
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'); } ]; } }
Run it using:
$ xp -supervise web Service @xp.web.srv.Standalone(HTTP @ peer.ServerSocket(Resource id #61 -> tcp://127.0.0.1:8080)) # ...
Supports a development webserver which is slower but allows an easy edit/save/reload development process. It uses the PHP development server in the background.
$ xp -supervise web -m develop Service @xp.web.srv.Develop(HTTP @ `php -S [...] -t /home/example/devel/shorturl`) # ...
Now open the website at http://localhost:8080/hello
Server models
The server models (selectable via -m <model>[,argument[,argument...]] on the command line) are:
- async (the default): A single-threaded web server. Handlers can yield control back to the server to serve other clients during lengthy operations such as file up- and downloads.
- prefork: Much like Apache, forks a given number of children to handle HTTP requests. Requires the
pcntlextension. Useprefork,children=<n>to control the number of child processes. - develop: As mentioned above, built ontop of the PHP development webserver. Application code is recompiled and application setup performed from scratch on every request, errors and debug output are handled by the development console. Use
develop,workers=<n>to control the number of worker processes.
Request and response
The web.Request class provides the following basic functionality:
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
The web.Response class provides the following basic functionality:
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);
Both Request and Response have a stream() method for accessing the underlying in- and output streams.
Handlers
A handler (also referred to as middleware in some frameworks) is a function which receives a request and response and uses the above functionality to handle communication.
use web\Handler; $redirect= new class() implements Handler { public function handle($req, $res) { $req->status(302); $req->header('Location', 'https://example.com/'); } };
This library comes with web.handler.FilesFrom - a handler for serving files. It takes care of conditional requests (with If-Modified-Since) as well requests for content ranges, and makes use of the asynchronous capabilities if available, see here.
Filters
Filters wrap around handlers and can perform tasks before and after the handlers are invoked. You can use the request's pass() method to pass values - handlers can access these using 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()); } } }
By using yield from, you guarantee asynchronous handlers will have completely executed before the time measurement is run on in the finally block.
File uploads
File uploads are handled by the request's multipart() method. In contrast to how PHP works, file uploads are streamed and your handler starts running with the first byte transmitted!
use io\Folder; $uploads= new Folder('...'); $handler= function($req, $res) use($uploads) { if ($multipart= $req->multipart()) { // See https://developer.mozilla.org/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... } };
Early hints
An experimental status code with which headers can be sent to a client early along for it to be able to make optimizations, e.g. preloading scripts and stylesheets.
$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'); }
See https://evertpot.com/http/103-early-hints
Internal redirects
On top of external redirects which are triggered by the 3XX status codes, requests can also be redirected internally using the dispatch() method. This has the benefit of not requiring clients to perfom an additional request.
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'); }, ]; } }
WebSockets
To use two-way interactive communication sessions between the user's browser and our server, route to the WebSocket handler as follows:
use web\Application; use web\handler\WebSocket; class Ws extends Application { public function routes() { return [ '/ws/echo' => new WebSocket(function($conn, $payload) { $conn->send('You said: '.$payload); }), '/' => function($request, $response) { $html= <<<'HTML' <!-- Shortened for brevity --> <script type="module"> const socket = new WebSocket(`ws://${location.host}/ws/echo`); socket.addEventListener('open', e => socket.send('Hello World!')); socket.addEventListener('message', e => console.log(e.data)); </script> HTML; $res->send($html, 'text/html; charset=utf-8'); } ]; } }
See https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
Logging
By default, logging goes to standard output and will be visible in the console the xp web command was invoked from. It can be influenced via the command line as follows:
-l server.log: Writes to the file server.log, creating it if necessary-l -: Writes to standard output-l - -l server.log: Writes to both of the above
More fine-grained control as well as integrating with the logging library can be achieved from inside the application, see here.
Performance
Because the code for the web application is only compiled once when using production servers, we achieve lightning-fast request/response roundtrip times:
See also
This library provides for the very basic functionality. To create web frontends or REST APIs, have a look at the following libraries built ontop of this:
xp-forge/web 适用场景与选型建议
xp-forge/web 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 138.79k 次下载、GitHub Stars 达 2, 最近一次更新时间为 2017 年 05 月 07 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「module」 「xp」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 xp-forge/web 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 xp-forge/web 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 xp-forge/web 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
bootstrap select field module implementing http://silviomoreto.github.io/bootstrap-select/
Yii2 module to manage website content. Kind of a CMS...
Codeurx Modular is simply a package for Laravel to help you create and manage modules.
User Module for the Attogram Framework
Info Module for the Attogram Framework
Contact Form Module for the Attogram Framework
统计信息
- 总下载量: 138.79k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 9
- 依赖项目数: 6
- 推荐数: 0
其他信息
- 授权协议: BSD-3-Clause
- 更新时间: 2017-05-07

