HTTP 响应

Slim 应用程序的路由和中间件给出了一个 PSR 7 响应对象,它表示当前的 HTTP 响应将被返回给客户端。该响应对象遵循 PSR 7 响应接口实现,因此你可以检查和操作该 HTTP 响应的状态、响应头和响应体。

如何获取 HTTP 响应对象

PSR 7 响应对象作为路由回调的第二个参数注入到 Slim 应用程序的路由中:

<?php
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

$app = new \Slim\App;
$app->get('/foo', function (ServerRequestInterface $request, ResponseInterface $response) {
    // Use the PSR 7 $response object

    return $response;
});
$app->run();
Figure 1: Inject PSR 7 response into application route callback.

PSR 7 请求对象作为中间件 callable 的第二个参数注入到 Slim 应用程序的中间件

<?php
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

$app = new \Slim\App;
$app->add(function (ServerRequestInterface $request, ResponseInterface $response, callable $next) {
    // Use the PSR 7 $response object

    return $next($request, $response);
});
// Define app routes...
$app->run();
Figure 2: Inject PSR 7 response into application middleware.

HTTP 响应状态

每个 HTTP 响应都有一个数字 状态编码。状态编码用于识别返回客户端的 HTTP 响应的类型。PSR 7 响应对象的默认状态编码是 200 (OK)。你可以像这样使用 getStatusCode() 方法获取 PSR 7 响应对象的状态编码:

$status = $response->getStatusCode();
Figure 3: Get response status code.

你可以拷贝一个 PSR 7 响应对象,并指定一个新的状态编码,像这样:

$newResponse = $response->withStatus(302);
Figure 4: Create response with new status code.

HTTP 响应头

每个 HTTP 响应都有其相应的响应头。这些元数据描述了 HTTP 响应,但在响应体中不可见。Slim 的 PSR 7 响应对象提供了几种检查和操作响应头的方法。

获取所有响应头

使用 PSR 7 响应对象的 getHeaders() 方法提取所有 HTTP 响应头并存入一个关联数组中。该关联数组的键名即为响应头的名称,键值是与其响应头对应的值的字符串数组。

$headers = $response->getHeaders();
foreach ($headers as $name => $values) {
    echo $name . ": " . implode(", ", $values);
}
Figure 5: Fetch and iterate all HTTP response headers as an associative array.

获取单个响应头

使用 PSR 7 响应对象的 getHeader($name) 方法获取单个响应头的值。它将返回指定响应头的值组成的数组。记住,单个 HTTP 响应不止一个值。

$headerValueArray = $response->getHeader('Vary');
Figure 6: Get values for a specific HTTP header.

同样,可以是 PSR 7 响应对象的 getHeaderLine($name) 方法获取指定响应头的所有值,由逗号隔开。不同于 getHeader($name) 方法,此方法返回的是由逗号隔开的字符串。

$headerValueString = $response->getHeaderLine('Vary');
Figure 7: Get single header's values as comma-separated string.

检查响应头

使用 PSR 7 响应对象的 hasHeader($name) 方法检查响应头存在与否。

if ($response->hasHeader('Vary')) {
    // Do something
}
Figure 8: Detect presence of a specific HTTP header.

设置响应头

使用 PSR 7 响应对象的 withHeader($name, $value) 方法设置响应头的值。

$newResponse = $oldResponse->withHeader('Content-type', 'application/json');
Figure 9: Set HTTP header
提示
响应对象是不可改的。此方法返回一个响应对象的拷贝(copy),它拥有新的值。此方法是破坏性的,它替换了已有的同名响应头现有的值。

追加响应头/Append Header

使用 PSR 7 响应对象的 withAddedHeader($name, $value) 方法追加一个响应头的值。

$newResponse = $oldResponse->withAddedHeader('Allow', 'PUT');
Figure 10: Append HTTP header
提示
不同于 withHeader() 方法,此方法是追加(append)新的值到响应头已有的值中。该响应对象是不可修改的。此方法返回一个已添加新值的该对象的拷贝

移除响应头

使用 HTTP 响应对象的 withoutHeader($name) 方法移除响应头。

$newResponse = $oldResponse->withoutHeader('Allow');
Figure 11: Remove HTTP header
Reminder
The Response object is immutable. This method returns a copy of the Response object that has the appended header value.

HTTP 响应体

HTTP 响应通常有一个响应体。Slim 提供了一个 PSR 7 响应对象让你可以检查或操作可能会有的响应体。

类似 PSR 7 请求对象,PSR 7 响应对象是\Psr\Http\Message\StreamInterface 实例的实现。你可以使用 PSR 7 响应对象的 getBody() 方法来获取 HTTP 响应体 StreamInterface 的实例。该 getBody() 方法完美适用于未知大小或对于可用内容来说太大的 HTTP 响应。

$body = $response->getBody();
Figure 12: Get HTTP response body

所得的 \Psr\Http\Message\StreamInterface 实例提供以下方法来读取、迭代、写入到潜在的 PHP资源(resource)

  • getSize()
  • tell()
  • eof()
  • isSeekable()
  • seek()
  • rewind()
  • isWritable()
  • write($string)
  • isReadable()
  • read($length)
  • getContents()
  • getMetadata($key = null)

大多数情况下,你会需要写入到 PSR 7 响应对象。你可以像这样使用 write() 方法将内容写入到 StreamInterface 实例:

$body = $response->getBody();
$body->write('Hello');
Figure 13: Write content to the HTTP response body

你同样可以完整新建一个 StreamInterface 实例来替换 PSR 7 响应对象的响应体。这玩意特别有用,尤其是你想要从远程地址传输内容到 HTTP 响应中时(例如,文件系统或远程API)。你可以使用 withBody(StreamInterface $body) 方法替换 PSR 7 响应对象的响应体。它的参数必须\Psr\Http\Message\StreamInterface 的实例。

$newStream = new \GuzzleHttp\Psr7\LazyOpenStream('/path/to/file', 'r');
$newResponse = $oldResponse->withBody($newStream);
Figure 14: Replace the HTTP response body
提示
响应对象不可改变。这个方法返回的是包含新响应体的对象的拷贝(copy)

Returning JSON

Slim’s Response object has a custom method withJson($data, $status, $encodingOptions) to help simplify the process of returning JSON data.

The $data parameter contains the data structure you wish returned as JSON. $status is optional, and can used to return a custom HTTP code. $encodingOptions is optional, and are the same encoding options used for json_encode().

In it’s simplest form, JSON data can be returned with a default 200 HTTP status code.

$data = array('name' => 'Bob', 'age' => 40);
$newResponse = $oldResponse->withJson($data);
Figure 15: Returning JSON with a 200 HTTP status code.

We can also return JSON data with a custom HTTP status code.

$data = array('name' => 'Rob', 'age' => 40);
$newResponse = $oldResponse->withJson($data, 201);
Figure 16: Returning JSON with a 201 HTTP status code.

The Content-Type of the Response is automatically set to application/json;charset=utf-8.

If there is a problem encoding the data to JSON, a \RuntimeException($message, $code) is thrown containing the values of json_last_error_msg() as the $message and json_last_error() as the $code.

Reminder
The Response object is immutable. This method returns a copy of the Response object that has a new Content-Type header. This method is destructive, and it replaces the existing Content-Type header. The Status is also replaced if a $status was passed when withJson() was called.