将请求 header 与 HTTP 客户端一起使用到外部 Api 服务器
Use a request header with HTTP Client to external Api server
考虑以下对 Symfony 控制器的请求:
http http://127.0.0.1:8000/index x-token:1000
#[Route('/index', name: 'index')]
public function index(HttpClientInterface $client, Request $request): Response
{
$client->request('GET', 'http://0.0.0.0:3001', ['headers' => ['x-token' => $request->headers->get('x-token')]]);
return new JsonResponse();
}
此代码片段是在控制器中使用的最小示例。控制器接受请求,并使用 x-token
header 对第 3 方进行身份验证 Api(此处:localhost:3001)。
有没有办法使这个过程自动化?所以基本上 - 监听传入的请求并将 x-token
header 注入 Symfony 中的特定 Scoped Client or the default client。
目标是,不是在每次使用 Http 客户端时都这样做,而是配置客户端服务。
客户端将在整个代码库中使用,而不仅仅是在这个最小示例中的控制器中。
我知道我可以使用 Service Decoration 并扩展正在使用的客户端。我无法连接点并使它起作用。
您尝试过使用 symfony kernel events 吗?
首先,如果您要调用一些第 3 方 api,我建议您在基础设施层创建一个单独的 class,例如 MyApiProvider
。直接从你的控制器使用 HttpClient 并不聪明,因为你可能还想调整一些东西(例如 api 主机等)。所以它看起来像这样:
<?php
namespace App\Infrastructure\Provider;
class MyApiProvider
{
// Of course, this also be better configurable via your .env file
private const HOST = 'http://0.0.0.0:3001';
private HttpClientInterface $client;
private ?string $token = null;
public function __construct(HttpClientInterface $client)
{
$this->client = $client;
}
public function setToken(string $token): void
{
$this->token = $token;
}
public function getSomething(): array
{
$response = $this->client->request(
'GET',
self::HOST,
['headers' => $this->getHeaders()]
);
return $response->toArray();
}
private function getHeaders(): array
{
$headers = [];
if ($this->token !== null) {
$headers['x-token'] = $this->token;
}
return $headers;
}
}
然后您需要使用 symfony 的 kernel.request
事件从请求中向您的提供商注入令牌:
<?php
namespace App\Event;
use Symfony\Component\HttpKernel\Event\KernelEvent;
class RequestTokenEventListener
{
private MyApiProvider $provider;
public function __construct(MyApiProvider $provider)
{
$this->provider = $provider;
}
public function onKernelController(KernelEvent $event): void
{
$request = $event->getRequest();
$token = $request->headers->get('x-token');
if ($token !== null) {
$this->provider->setToken($token);
}
}
}
最后是你的控制器:
#[Route('/index', name: 'index')]
public function index(MyApiProvider $provider): Response
{
$provider->getSomething();
return new JsonResponse();
}
因此,如果令牌已通过,您的提供商将在每个请求期间拥有令牌上下文。
考虑以下对 Symfony 控制器的请求:
http http://127.0.0.1:8000/index x-token:1000
#[Route('/index', name: 'index')]
public function index(HttpClientInterface $client, Request $request): Response
{
$client->request('GET', 'http://0.0.0.0:3001', ['headers' => ['x-token' => $request->headers->get('x-token')]]);
return new JsonResponse();
}
此代码片段是在控制器中使用的最小示例。控制器接受请求,并使用 x-token
header 对第 3 方进行身份验证 Api(此处:localhost:3001)。
有没有办法使这个过程自动化?所以基本上 - 监听传入的请求并将 x-token
header 注入 Symfony 中的特定 Scoped Client or the default client。
目标是,不是在每次使用 Http 客户端时都这样做,而是配置客户端服务。
客户端将在整个代码库中使用,而不仅仅是在这个最小示例中的控制器中。
我知道我可以使用 Service Decoration 并扩展正在使用的客户端。我无法连接点并使它起作用。
您尝试过使用 symfony kernel events 吗?
首先,如果您要调用一些第 3 方 api,我建议您在基础设施层创建一个单独的 class,例如 MyApiProvider
。直接从你的控制器使用 HttpClient 并不聪明,因为你可能还想调整一些东西(例如 api 主机等)。所以它看起来像这样:
<?php
namespace App\Infrastructure\Provider;
class MyApiProvider
{
// Of course, this also be better configurable via your .env file
private const HOST = 'http://0.0.0.0:3001';
private HttpClientInterface $client;
private ?string $token = null;
public function __construct(HttpClientInterface $client)
{
$this->client = $client;
}
public function setToken(string $token): void
{
$this->token = $token;
}
public function getSomething(): array
{
$response = $this->client->request(
'GET',
self::HOST,
['headers' => $this->getHeaders()]
);
return $response->toArray();
}
private function getHeaders(): array
{
$headers = [];
if ($this->token !== null) {
$headers['x-token'] = $this->token;
}
return $headers;
}
}
然后您需要使用 symfony 的 kernel.request
事件从请求中向您的提供商注入令牌:
<?php
namespace App\Event;
use Symfony\Component\HttpKernel\Event\KernelEvent;
class RequestTokenEventListener
{
private MyApiProvider $provider;
public function __construct(MyApiProvider $provider)
{
$this->provider = $provider;
}
public function onKernelController(KernelEvent $event): void
{
$request = $event->getRequest();
$token = $request->headers->get('x-token');
if ($token !== null) {
$this->provider->setToken($token);
}
}
}
最后是你的控制器:
#[Route('/index', name: 'index')]
public function index(MyApiProvider $provider): Response
{
$provider->getSomething();
return new JsonResponse();
}
因此,如果令牌已通过,您的提供商将在每个请求期间拥有令牌上下文。