guide42 / ochenta
HTTP 请求/响应实现
v0.6.0
2020-06-09 14:05 UTC
Requires
- php: >=7.2
Requires (Dev)
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