PHP - Guzzle 中间件

Rem*_*emi 0 php middleware http guzzle

我正在使用 Pole Emploi 的 API,但 25 分钟后,当我的令牌过期时,我遇到了 401 错误。

我寻找一种获取新令牌并重试请求的方法,但我无法理解中间件的工作原理,以及我是否应该使用中间件来满足我的需求。

在 Guzzle 的文档上是这样写的:

中间件函数返回一个接受下一个要调用的处理程序的函数。然后,这个返回的函数返回另一个充当组合处理程序的函数——它接受请求和选项,并返回一个通过响应实现的承诺。您组合的中间件可以修改请求、添加自定义请求选项以及修改下游处理程序返回的 Promise。

这是文档中的示例代码:

use Psr\Http\Message\RequestInterface;

function my_middleware()
{
    return function (callable $handler) {
        return function (RequestInterface $request, array $options) use ($handler) {
            return $handler($request, $options);
        };
    };
}
Run Code Online (Sandbox Code Playgroud)

所以我认为我需要管理“承诺”以查看其HTTP代码是否为401,然后获取新令牌并重试请求?

我迷路了,所以如果有人能用不同的词向我解释这个逻辑,我将不胜感激:)

先感谢您。

小智 6

不需要那么困难,添加一个处理该作业的处理程序,并结合过期的缓存。

如果您不使用缓存,那么我想您可能可以将其与过期时间戳一起保存到文件中,以便在获取它时进行检查。

class AuthenticationHandler
{
    private $username;
    private $password;
    private $token_name = 'access_token';

    public function __construct($username, $password)
    {
        $this->username = $username;
        $this->password = $password;
    }

    public function __invoke(callable $handler)
    {
        return function (RequestInterface $request, array $options) use ($handler) {
            if (is_null($token = Cache::get($this->token_name))) {
                $response = $this->getJWT();
                Cache::put($this->token_name, $token = $response->access_token, floor($response->expires_in));
            }

            return $handler(
                $request->withAddedHeader('Authorization', 'Bearer '.$token)
                    ->withAddedHeader('Api-Key', $this->api_key), $options
                );
        };
    }

    private function getJWT()
    {
        $response = (new Client)->request('POST', 'new/token/url', [
            'form_params' => [
                'grant_type' => 'client_credentials',
                'username' => $this->username,
                'password' => $this->password,
            ],
        ]);
        return json_decode($response->getBody());
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用它:

$stack = HandlerStack::create(new CurlHandler());
$stack->push(new AuthenticationHandler('username', 'password'));
$client = new GuzzleHttp\Client([
    'base_uri' => 'https://api.com',
    'handler' => $stack,
]);
Run Code Online (Sandbox Code Playgroud)

现在您将始终拥有一个有效的令牌,并且您再也不用担心它了。