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.
Advertisement
Answer
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 AppInfrastructureProvider; 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 AppEvent; use SymfonyComponentHttpKernelEventKernelEvent; 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.