neat / http-server
Neat HTTP服务器组件
0.2.3
2024-08-15 08:11 UTC
Requires
- php: ^7.2 || ^8.0
- neat/http: ^0.6.3
- psr/http-factory: ^1.0
- psr/http-message: ^1.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- phpunit/phpunit: ^6.5 || ^7.0 || ^8.0 != 8.5.0
README
Neat HTTP服务器组件为您的应用程序提供了一种干净、易于表达的API,用于接收HTTP请求和发送HTTP响应。
要求
要使用Neat HTTP服务器组件,您需要
- PHP 7.0或更高版本
- PSR-7 HTTP消息实现
- PSR-17 HTTP工厂实现
入门
要安装此包,只需在命令行中运行composer
composer require neat/http-server
服务器
// Create a PSR-17 factory $factory = new Example\Factory(); // Then create the server using this factory (three interfaces are required) $server = new Neat\Http\Server\Server($factory, $factory, $factory); // Write a handler to handle incoming requests $handler = new Neat\Http\Server\Handler\CallableHandler(function (Neat\Http\Server\Request $request) { // return new Neat\Http\Response(...); });
然后使用服务器接收请求,处理请求并发送响应
/** @var Neat\Http\Server\Server $server */ /** @var Neat\Http\Server\Handler $handler */ // Receive the request $request = $server->receive(); // Handle the request $response = $handler->handle($request); // Send the response $server->send($response);
处理器
处理器可以从头开始使用处理器接口编写,或者使用提供的适配器之一创建
// Write a handler from scratch class Handler implements Neat\Http\Server\Handler { /** @noinspection PhpInconsistentReturnPointsInspection */ public function handle(Neat\Http\Server\Request $request): Neat\Http\Response { // return new Neat\Http\Response(...); } } // Alternatively write a handler using a closure $handler = new Neat\Http\Server\Handler\CallableHandler(function (Neat\Http\Server\Request $request) { // return new Neat\Http\Response(...); }); // Or use an existing PSR-15 RequestHandlerInterface implementation /** @var Psr\Http\Server\RequestHandlerInterface $psr */ $handler = new Neat\Http\Server\Handler\PsrHandler($psr);
中间件
要拦截传入的请求、传出的响应以及可能出现的异常,您可以创建一个中间件,为您的处理器和进出消息添加额外的控制层。
// Write a middleware from scratch class Middleware implements Neat\Http\Server\Middleware { public function process(Neat\Http\Server\Request $request, Neat\Http\Server\Handler $handler): Neat\Http\Response { return $handler->handle($request); } } // Or using a closure $handler = new Neat\Http\Server\Middleware\CallableMiddleware( function (Neat\Http\Server\Request $request, Neat\Http\Server\Handler $handler) { return $handler->handle($request); });
分发器
要处理请求时使用中间件,您可以使用分发器。
// Assuming we have a handler readily available, we can create a Dispatcher // with a stack of one or more Middleware instances /** @var Neat\Http\Server\Handler $handler */ $dispatcher = new Neat\Http\Server\Dispatcher( $handler, new Neat\Http\Server\Middleware\CallableMiddleware(function () { /* ... */ }), new Neat\Http\Server\Middleware\CallableMiddleware(function () { /* ... */ }) ); // Then using the request we can ask the dispatcher to handle the request and // return the response from the handler through the middleware. /** @var Neat\Http\Server\Request $request */ $response = $dispatcher->handle($request);
输出
从控制器创建响应非常简单
// First create the output helper using a PSR-17 factory and a templating renderer $factory = new Example\Factory(); $output = new Neat\Http\Server\Output($factory, $factory, function (string $template, array $data) { // Use any templating engine you like and return the rendered result as a string }); // Then create a simple text response (it will have the proper Content-Length and Content-Type header set) $response = $output->text('Hello world!'); // Or an html response (with the text/html Content-Type header) $response = $output->html('<html lang="en"><body>Hi!</body></html>'); // Us a custom body and add headers afterwards $response = $output->body('{key:"value"}')->withContentType('application/json'); // Or just let the output create a JSON response directly $response = $output->json(['key' => 'value']); // There's even XML support $response = $output->xml('<document><title>Long live XML</title></document>'); // Rendering a template view is just as easy using the output helper $response = $output->view('template', ['message' => 'Hello world!']); // Download a file $response = $output->download(fopen('path/to/really/large/file.bin', 'r+')); // Display it inline $response = $output->display('path/to/file.pdf'); // Other types of responses $response = $output->response(404, 'Page not found');
重定向
使用重定向输出助手将客户端重定向到另一个URL非常简单。
/** @var Neat\Http\Server\Input $input */ /** @var Neat\Http\Server\Output $output */ /** @var Neat\Http\Server\Request $request */ // Redirect to a url $response = $output->redirect()->to('/go/there/instead'); // Redirect permanently $response = $output->redirect()->permanent()->to('/go/there/instead'); // Redirect and resubmit $response = $output->redirect()->resubmit()->to('/submit/there/instead'); // Redirect back to the referring url $response = $output->redirect()->back($request); // Refresh $response = $output->redirect()->refresh($request); // Retry input $response = $output->redirect()->retry($input);
在您的处理器中,您可以使用输出助手将除Neat\Http\Response以外的任何返回值转换为响应。
$factory = new Example\Factory(); $output = new Neat\Http\Server\Output($factory, $factory); // By default any value that isn't a Neat\Http\Response will be converted to a JSON response $response = $output->resolve(['What now?' => 'My controller just returned this lousy array.']); // You can learn the output to handle any type using a Response factory $output->register('string', function (string $string) use ($output) { return $output->html($string); }); $response = $output->resolve('HELP my controller just returned a string!'); // Null could be your way of returning a 204 No content response $output->register('null', function () use ($output) { return $output->response(204); }); // If you want objects with a __toString method to convert differently $output->register('object', function ($object) use ($output) { if (method_exists($object, '__toString')) { return (string) $object; } return $output->json($object); }); // You can even target specific classes or interfaces $output->register(Psr\Http\Message\StreamInterface::class, function (Psr\Http\Message\StreamInterface $stream) use ($output) { return $output->response()->withBody($stream); });