Consider the following request to a Symfony controller:
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();
}
This code snippet is a minimal example for the usage in a controller. The controller accepts a Request, and uses the x-token
header for authenticating against the 3rd Party Api (here: localhost:3001).
Is there a way, to automate this process? So basically - listen to incoming requests and inject the x-token
header into a specific Scoped Client or the default client in Symfony.
The goal is, not to do this in every usage of the Http Client, but have a configured client service.
The client will be used all over the codebase, not just in a controller like in this minimal example.
I know that I can use Service Decoration and extend the clients in use. I fail how to connect the dots and make this work.
CodePudding user response:
Have you tried using symfony kernel events?
First of all, if you are calling some 3rd-party api, I'd suggest you to create a separate class at the infrastructure layer, for example MyApiProvider
. Using HttpClient right from your controller is not smart, because you may also want to adjust something (for example api host, etc). So it's gonna look like this:
<?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;
}
}
Then you need to use symfony's kernel.request
event to inject token to your provider from the 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);
}
}
}
And finally your controller:
#[Route('/index', name: 'index')]
public function index(MyApiProvider $provider): Response
{
$provider->getSomething();
return new JsonResponse();
}
So your provider is gonna have token context during each request, if the token is passed.