我正在使用Pole Emploi的API,但是25分钟后,当我的令牌过期时,我遇到401错误。
我在寻找一种获取新令牌并重试请求的方法,但我没有办法了解中间件的工作方式,以及是否应根据需要使用中间件。
在Guzzle的文档中这样写:
中间件函数返回一个接受下一个要调用的处理程序的函数。然后,此返回的函数返回充当组合处理程序的另一个函数-它接受请求和选项,并返回通过响应实现的promise。您组成的中间件可以修改请求,添加自定义请求选项以及修改下游处理程序返回的承诺。
这是docs中的示例代码:
use Psr\Http\Message\RequestInterface;
function my_middleware()
{
return function (callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
return $handler($request, $options);
};
};
}
所以我认为我需要管理“承诺”以查看其HTTP代码是否为401,然后获取新令牌并重试请求?
我迷路了,所以如果有人可以用不同的词来解释这个逻辑,我将不胜感激:)
谢谢。
答案 0 :(得分:2)
并不需要那么困难,添加一个负责该工作的处理程序以及过期的缓存。
如果您不使用缓存,那么我想您可以将其与时间戳一起保存到文件中,以便在提取时进行检查。
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());
}
}
然后使用它:
$stack = HandlerStack::create(new CurlHandler());
$stack->push(new AuthenticationHandler('username', 'password'));
$client = new GuzzleHttp\Client([
'base_uri' => 'https://api.com',
'handler' => $stack,
]);
现在,您将始终拥有有效的令牌,并且您将不必再担心它。
答案 1 :(得分:0)
我不建议您这样做,因为它可能会调试您的应用程序,而且据我所知Guzzle确实不允许中间件访问客户端。无论如何,您都可以使用Promises来解决问题。如果您是我,我会在其他请求之前刷新令牌,或者定期刷新。如果您一个接一个地发出请求,可能会很好,但是在Pool中,这将成为一场噩梦,因为您最终可能会过于频繁地获取脚本脚本,然后某些请求最终会使用过期的令牌。
无论如何,这是一个粗糙的例子:
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
function my_middleware()
{
return function (callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
/**
* @var $promise \GuzzleHttp\Promise\Promise
*/
$promise = $handler($request, $options);
return $promise->then(
function (ResponseInterface $response) use ($request, $options) {
if ($response->getStatusCode() === 404) {
var_dump($response->getStatusCode());
var_dump(strlen($response->getBody()));
// Pretend we are getting new token key here
$client = new Client();
$key = $client->get('https://www.iana.org/domains/reserved');
// Then we modify the failed request. For your case you use ->withHeader() to change the
// Authorization header with your token.
$uri = $request->getUri();
$uri = $uri->withHost('google.com')->withPath('/');
// New instance of Request
$request = $request->withUri($uri);
// Send the request again with our new header/URL/whatever
return $client->sendAsync($request, $options);
}
return $response;
}
);
};
};
}
$handlerStack = HandlerStack::create();
$handlerStack->push(my_middleware());
$client = new Client([
'base_uri' => 'https://example.org',
'http_errors' => false,
'handler' => $handlerStack
]);
$options = [];
$response = $client->request('GET', '/test', $options);
var_dump($response->getStatusCode());
var_dump(strlen($response->getBody()));
echo $response->getBody();