neat/http-server

Neat HTTP服务器组件

0.2.3 2024-08-15 08:11 UTC

This package is auto-updated.

Last update: 2024-09-15 08:23:48 UTC


README

Stable Version Build Status

Neat HTTP服务器组件为您的应用程序提供了一种干净、易于表达的API,用于接收HTTP请求和发送HTTP响应。

要求

要使用Neat 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);
});