PSR 18 HTTP 客户端 「起草中」
本篇规范是发送 HTTP 请求和接收 HTTP 响应的通用接口规范
本篇规范中的 必须,不得,需要,应,不应,应该,不应该,推荐,可能 和 可选 等词按照 RFC 2119 中的描述进行解释
规范
客户端
-
一个 HTTP 客户端是可以发送符合 PSR-7 规范的 HTTP 请求和接收符合 PSR-7 规范的 HTTP 响应
-
在底层实现中,HTTP 客户端 可能 会修改从用户/服务器接收到的请求/响应,在这种情况下,必须保持请求和响应中的头部信息和内容必须一致,例如服务器可能会返回一个经过 gzip 压缩的响应内容,客户端就要知道如何去解码
-
当解码 HTTP 响应的内容时,HTTP 客户端 必须 删除指定编码的响应头和调整
Content-Length
响应头
异常
HTTP 客户端抛出的每一个异常都 必须 实现 Psr\Http\Client\ClientException
接口
当传递给 HTTP 客户端的请求不可用或不能被发送时,客户端 必须 抛出一个 Psr\Http\Client\Exception\RequestException
异常
当发生了网络错误或远程服务器不可访问时,客户端 必须 抛出 Psr\Http\Client\Exception\NetworkException
异常
一些较小的问题,例如使用了错误的 HTTP 版本号,只要不会阻止 HTTP 客户端发送请求,那么就 不应该 抛出任何异常
如果远程服务器返回了一个遵循 PSR-7 规范的响应,即使返回的响应状态码是 400 或 500,客户端也 不应该 抛出任何异常
设计目标
此 PSR 的目标是允许开发人员创建与 HTTP 客户端实现相分离的库,这样使得库更加可重用,因为它减少了依赖关系的数量并降低了版本冲突的可能性
第二个目标是可以根据 里氏替换原则 替换 HTTP 客户端。也就是说所有客户端在发送请求时都 必须 能以相同的方式运行
接口
客户端接口
<?php namespace Psr\Http\Client; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; interface ClientInterface { /** * 发送一个遵循 PSR-7 的请求和返回一个遵循 PSR-7 的响应 * * 任何一个技术上正确的 HTTP 响应都 **必须** 原样返回,无论是 HTTP 错误还是重定向指令 * 唯一的特例就是 1xx 响应,它 **必须** 由 HTTP 客户端来处理 * * 客户端可以在发送请求前对请求做一些修改。 不能因为符合 PSR-7 规范的请求对象是不可变的,就假定发送的请求就和传递给 ·ClientInterface::sendRequest()` 是同一个对象 * * 实际发送的请求对象,例如因发生异常而返回的请求对象 **可能** 和传递给 sendRequest 的不一样, 因此通过恒等于号 ( === ) 比较是不可取的 * * {@link https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message-meta.md#why-value-objects} * * @param RequestInterface $request * * @return ResponseInterface * * @throws \Psr\Http\Client\ClientException 请求过程中发生错误则抛出异常 */ public function sendRequest(RequestInterface $request): ResponseInterface; }
Exception
<?php namespace Psr\Http\Client; /** * 每一个和 HTTP 客户端相关的异常都应该实现该接口 */ interface ClientException extends \Throwable { }
RequestException
<?php namespace Psr\Http\Client\Exception; use Psr\Http\Client\ClientException; use Psr\Http\Message\RequestInterface; /** * 请求失败时抛出的异常 * * 例如 * - 请求错误 (e.g. 没有设置请求方法) * - 请求过程中发生错误 (e.g. 请求的数据流不能访问) */ interface RequestException extends ClientException { /** * 返回请求对象 * * 返回的请求对象 **可以** 和使用 `ClientInterface::sendRequest()` 设置的请求对象不一样 * * @return RequestInterface */ public function getRequest(): RequestInterface; }
NetworkException
<?php namespace Psr\Http\Client\Exception; use Psr\Http\Client\ClientException; use Psr\Http\Message\RequestInterface; /** * 由于网络问题而不能完成请求时抛出该异常 * * 抛出此异常后不应该返回响应对象,因为没有接收到任何响应 * * 例如:目标主机地址无法解析 */ interface NetworkException extends ClientException { /** * 返回请求对象 * * 返回的请求对象 **可以** 和使用 `ClientInterface::sendRequest()` 设置的请求对象不一样 * * @return RequestInterface */ public function getRequest(): RequestInterface; }