1 回答
TA贡献1906条经验 获得超10个赞
这是我的看法,主要基于尝试几种方法。
任何PSR-18 客户端都会有一个必须遵守的接口。该接口本质上只是一种方法 - sendRequest()
. 该方法将发送PSR-7 请求 并返回PSR-7 响应。
请求中的大部分内容将用于构建 PSR-7 请求。这将在它sendRequest()
到达客户之前放在一起。PSR-18 规范没有定义的是客户端的行为,比如是否遵循重定向。它确实指定在非 2XX 响应的情况下不应引发异常。
这可能看起来非常有限制,但这个客户端是最后,它只关心请求的物理发送和响应的捕获。有关客户端行为的所有其他内容都可以内置到 中间件中以扩展该客户端。
那么 PSR-18 中间件可以做什么呢?
它可以访问原始 PSR-7 请求,因此可以读取和更改请求。
它可以访问 PSR-7 响应,因此它可以修改响应,并根据该响应采取行动。
它发出
sendRequest()
调用,因此可以应用处理方式的逻辑,例如重试、跟随重定向等。
PSR-18 规范没有提到中间件,那么它会放在哪里呢?一种实现方式可能是装饰器。装饰器包裹基本 PSR-18 客户端,添加功能,但会将自己呈现为 PSR-18 客户端。这意味着可以在基本客户端上分层多个装饰器以添加您喜欢的任意数量的功能。
这是一个 PSR-18 装饰器的示例。这个装饰器本质上什么都不做,但提供了一个框架来放入逻辑。
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
class Psr18Decorator implements ClientInterface
{
// ClientInterface
protected $client;
// Instantiate with the current PSR-18 client.
// Options could be added here for configuring the decorator.
public function __construct(ClientInterface $client)
{
$this->client = $client;
}
public function sendRequest(RequestInterface $request): ResponseInterface
{
// The request can be processed here.
// Send the request, just once in this example.
$response = $this->client->sendRequest($request);
// The response can be processed or acted on here.
return $response;
}
// This is added so that if a decorator adds new methods,
// they can be accessed from the top, multiple layers deep.
public function __call($method, $parameters)
{
$result = $this->client->$method(...$parameters);
return $result === $this->client ? $this : $result;
}
}
所以给定基本的 PSR-18 客户端,它可以这样装饰:
$decoratedPsr18Client = new Psr18Decorator($basePsr18Client);
可以编写每个装饰器来处理单个关注点。例如,如果响应未返回 2XX 代码,您可能希望抛出异常。可以编写一个装饰器来做到这一点。
另一个装饰器可以处理 OAuth 令牌,或监控对 API 的访问,因此可以对其进行速率限制。另一个装饰器可以跟随重定向。
那么,您需要自己编写所有这些装饰器吗?就目前而言,是的,因为不幸的是周围缺乏它们。然而,由于它们是作为包开发和发布的,它们本质上是可重用的代码,可以应用于任何 PSR-18 客户端。
Guzzle 很棒,有很多功能,在这方面是单一的。我相信 PSR-18 方法应该允许我们将所有这些功能分解成更小的独立块,以便可以根据需要应用它们。装饰器管理包可能有助于添加这些装饰器(可能确保它们正确排序并相互兼容),并且可能以不同方式处理装饰器自定义方法以避免需要__call()回退。
我敢肯定还有其他方法,但这个方法对我来说效果很好。
- 1 回答
- 0 关注
- 152 浏览
添加回答
举报