guide42/ochenta

HTTP 请求/响应实现

v0.6.0 2020-06-09 14:05 UTC

This package is auto-updated.

Last update: 2024-09-22 00:17:15 UTC


README

  • HTTP 抽象:使用请求/响应对象代替全局变量。
  • HTTP 中间件:交叉请求到响应的过程。
  • HTTP 响应者:可执行视图,用于构建响应。

Hello World

use ochenta\ServerRequest;
use function ochenta\{emit, responder_of};

emit(new ServerRequest, responder_of('Hello World'));

感兴趣吗?继续阅读。

使用方法

$req = new ServerRequest;

也可以使用默认值创建

$req = new ServerRequest($_SERVER, $_GET, $_POST, $_FILES, $_COOKIE, fopen('php://input', 'rb'));

这是一个进入的请求。
超全局变量作为 $req->getQuery()$req->getParsedBody()$req->getFiles() 可用。

然后底层的 Request 抽象提供了更多方法

  • $req->getMethod()$req->getTarget() 从请求行。
  • $req->getHeaders() 获取所有头信息和 $req->getHost() 获取标准化域名。
  • $req->getMediaType()$req->getCharset() 来自 Content-Type 头。
  • $req->getAccept*() 返回解析后的 Accept* 头。

还有一个 Response 对象,但响应将由响应者提供。

响应者

在 SAPI 环境中工作,您可以使用响应者定义响应

function hola(ServerRequest $req, callable $open) {
    $name = $req->getQuery()['name'] ?? 'World';
    $open(200, ['Content-Language' => ['en', 'es']]);
    yield "Hola $name";
}

或使用 ochenta\Response 包装器

function hola(ServerRequest $req, callable $open) {
    $name = $req->getQuery()['name'] ?? 'World';
    $res = new Response(200, ['Content-Language' => ['en', 'es']], "Hola $name");
    return responder_of($response)($req, $open);
}

使用 ochenta\emit 函数,可以发出响应者

emit(new ServerRequest, @hola);

中间件

使用它们来包装您的 request -> responder 流程。这看起来像这样

function timeit(callable $handler): callable {
    return function(ServerRequest $req, callable $open) use($handler) {
        $time = -microtime(TRUE);
        $res = yield from $handler($req, $open);
        $time += microtime(TRUE);
        yield sprintf("<address>%.7F secs</address>", $time);
        return $res;
    };
}

装饰您的应用响应者

$app = @hola;
$app = timeit($app);

emit(new ServerRequest, $app);

当需要选项时,可以包装在另一个函数中。

function add_header(string $name, string $value): callable {
    return function(callable $handler) use($name, $value): callable {
        return function(ServerRequest $req, callable $open) use($name, $value, $handler) {
            return $handler($req, function(int $status, array $headers) use($name, $value, $open) {
                $headers[$name] = [$value];
                $open($status, $headers);
            });
        };
    };
}

复杂吗?这个中间件存在于 ochenta\header。这是使用方法

$app = add_header('X-Frame-Options', 'SAMEORIGIN')($app);

真麻烦!最好使用 ochenta\stack 来执行多个中间件

$app = stack(@hola, [
    add_header('X-Xss-Protection', '1; mode=block'),
    add_header('X-Frame-Options', 'SAMEORIGIN'),
    @timeit,
]);

您已经走得很远了。查看 example.php 以查看完整代码。

API

responder_of(Response $resource)                             // creates a responder from a Response
responder_of(resource $resource)                             // ... from a resource
responder_of(scalar $resource)                               // ... from content

emit(ServerRequest $req, callable $handler)                  // emits a responder

stack(callable $responder, array $stack)                     // expects stack items to be a function(callable $next)
stack(callable $responder, callable $resolver, array $stack) // ... use resolver as function(callable $prev, $handler)

// MIDDLEWARES

header(string $name, array $values)                          // adds a header to responder
header(string $name, string $value)                          // ... with single value

cookie(Cookie $cookie)                                       // sets cookie into responder

append(string $content)                                      // adds content before body
append(string $content, string $tag)                         // ... before every given tag

// RESPONDERS

redirect(string $uri)                                        // redirect to the given url
redirect(string $uri, int $statusCode)                       // ... with given status code

// CONTENT NEGOTATION

accept\mediatypes(Request $req, array $available)            // negotiate media types
accept\charsets(Request $req, array $available)              // ... charsets
accept\encodings(Request $req, array $available)             // ... encodings
accept\languages(Request $req, array $available)             // ... languages

// HELPERS

stream_of(scalar $resource)                                  // creates tmp file with $resouce content

徽章

Latest Stable Version Build Status Coverage Status