4

我试图了解 PSR-7 的工作原理,但我被卡住了!这是我的代码:

$app->get('/', function () {
    $stream = new Stream('php://memory', 'rw');
    $stream->write('Foo');
    $response = (new Response())
        ->withHeader('Content-Type', 'text/html')
        ->withBody($stream);
});

我的 Response 对象已构建,但现在我想发送它... PSR-7 如何发送响应?我需要序列化吗?我可能错过了一件事......

4

2 回答 2

7

就像完成一样,即使问题已经超过两年了:

响应是服务器向客户端发送的 HTTP 消息,是客户端向服务器发出请求的结果。

客户端需要一个字符串作为消息,包括:

  • 一个“状态行”(形式为HTTP/<protocol-version> <status-code> <reason-phrase>);
  • 标题列表(每个都以“ <header-name>: <comma-separ.-header-values>”的形式);
  • 空行;
  • 消息体(字符串)。

它看起来像这样(参见PSR-7):

HTTP/1.1 200 OK
Content-Type: text/html
vary: Accept-Encoding

This is the response body

为了发出响应,必须实际执行三个操作:

  1. “状态行”发送到客户端(使用header() PHP 函数)。
  2. 将标头列表发送给客户端( dito)。
  3. 输出消息体。

棘手的部分由第三个操作表示。一个实现类的实例ResponseInterface包含一个流对象作为消息体。并且这个对象必须转换为字符串并打印出来。这个任务很容易完成,因为流是一个实现类的实例StreamInterface,而后者又强制定义了一个神奇的方法__toString()

因此,通过执行前两个步骤并将输出函数(echoprint_r等)应用于getBody()响应实例的方法的结果,发射过程就完成了。

<?php
if (headers_sent()) {
    throw new RuntimeException('Headers were already sent. The response could not be emitted!');
}

// Step 1: Send the "status line".
$statusLine = sprintf('HTTP/%s %s %s'
        , $response->getProtocolVersion()
        , $response->getStatusCode()
        , $response->getReasonPhrase()
);
header($statusLine, TRUE); /* The header replaces a previous similar header. */

// Step 2: Send the response headers from the headers list.
foreach ($response->getHeaders() as $name => $values) {
    $responseHeader = sprintf('%s: %s'
            , $name
            , $response->getHeaderLine($name)
    );
    header($responseHeader, FALSE); /* The header doesn't replace a previous similar header. */
}

// Step 3: Output the message body.
echo $response->getBody();
exit();

PS:对于大量数据,最好使用php://temp流而不是php://memory. 就是原因。

于 2018-02-10T05:03:27.253 回答
4

Psr-7 只是为 http 消息建模。它没有发送响应的功能。您需要使用另一个使用 PSR-7 消息的库。你可以看看zend Stratigility或类似的东西

于 2015-10-23T15:17:11.710 回答