Programmation PHP avec Symfony/HttpClient
Installation
[modifier | modifier le wikicode]Composant pour lancer des requêtes HTTP depuis l'application, avec gestion des timeouts, redirections, cache, protocole et en-tête HTTP. Il est configurable en PHP ou dans framework.yaml.
Depuis Symfony 4[1] :
composer require symfony/http-client
Utilisation
[modifier | modifier le wikicode]Deux solutions :
HttpClient::create();
ou
public function __construct(private readonly HttpClientInterface $httpClient)
Par défaut, l'appel statique à la classe HttpClient instancie un CurlHttpClient, alors que l'injection du service via HttpClientInterface récupère un TraceableHttpClient. Ce dernier est préférable puisqu'il affiche toutes les requêtes dans le profiler de Symfony.
GET
[modifier | modifier le wikicode]On peut forcer l'utilisation de HTTP 2 à la création :
$httpClient = HttpClient::create(['http_version' => '2.0']);
$response = $httpClient->request('GET', 'https://fr.wikibooks.org/');
if (200 === $response->getStatusCode()) {
dd($response->getContent());
} else {
dd($response->getInfo('error'));
}
- Ce code ne lève pas les exceptions de résolution DNS.
- Mieux vaut éviter de créer le client HTTP ainsi car il n'apparaitra pas dans les logs, il faut injecter son service à la place, à partir de
HttpClientInterface.
Exemple avec query parameters :
$response = $this->httpClient->request('GET', 'https://fr.wikibooks.org/', ['query' => ['debug' => 1]]);
Cache
[modifier | modifier le wikicode]Symfony peut stocker les résultats des requêtes HTTP pour ne pas avoir à le refaire.
Depuis SF 7.4[2] :
http_client:
scoped_clients:
example.client:
base_uri: 'https://example.com'
caching:
cache_pool: example_cache_pool
Avant SF 7.4 :
$client = new CachingHttpClient($client, $store);
POST
[modifier | modifier le wikicode]Exemple en POST avec authentification :
$response = $httpClient->request('POST', 'https://fr.wikibooks.org/w/api.php', [
'auth_bearer' => 'mon_token',
'body' => $keyValuePairs,
]);
Pour lancer plusieurs appels asynchrones, il suffit de placer leurs $response->getContent() ensemble, après tous les $httpClient->request().
Pour envoyer un fichier il y a plusieurs solutions :
- Utiliser le type MIME correspondant à son extension (ex : 'application/pdf', 'application/zip'...). Mais on ne peut envoyer que le fichier dans la requête.
- Utiliser le type MIME 'application/json' et l'encoder en base64. Il peut ainsi être envoyé avec d'autres données.
- Utiliser le type MIME 'multipart/form-data'[3].
Problèmes connus
[modifier | modifier le wikicode]Ce composant est relativement jeune et souffre d'incomplétudes.
- On peut avoir du "null given" à tort sur un mapping DNS, solvable en rajoutant une option :
$options = array_merge($options, [
'resolve' => ['localhost' => '127.0.0.1']
]);
$httpClient->request()renvoie uneSymfony\Contracts\HttpClient\ResponseInterface, mais en cas d'erreur, elle ne contient qu'une ligne de résumé, soit moins d'informations qu'un client comme Postman.
Tests
[modifier | modifier le wikicode]Ce composant peut aussi serveur aux tests fonctionnels via PhpUnit. On l'appelle alors avec static::createClient si le test extends WebTestCase. Dans le cas d'un projet API Platform, on l'appelle de la même manière mais le test extends ApiTestCase.
Exemple :
$client = static::createClient();
$client->request('GET', '/home');
var_dump($client->getResponse()->getContent());
Pour simuler plusieurs clients en parallèle : $client->insulate().
Pour simuler un utilisateur : $client->loginUser($monUser).
Pour un test de bundle, il faut créer une classe Kernel qui charge les routes en plus[4].
Références
[modifier | modifier le wikicode]- ↑ https://symfony.com/doc/current/components/http_client.html
- ↑ https://symfony.com/blog/new-in-symfony-7-4-caching-http-client?utm_source=Symfony%20Blog%20Feed&utm_medium=feed
- ↑ https://dev.to/timoschinkel/sending-multipart-data-with-psr-18-2lb5
- ↑ https://symfonycasts.com/screencast/symfony-bundle/controller-functional-test

