New in Symfony 4.4: HttpClient Improvements

Contributed by
Nicolas Grekas
in #31641, #31831, #31976, #32104, #32231, and #32290.

The Symfony HttpClient component was introduced in Symfony 4.3 as a low-level HTTP client with support for both PHP stream wrappers and cURL. In Symfony 4.4 we've improved it with lots of new features.

In PR #31641 we made $response->getInfo('debug') to return extended logs about the HTTP transaction so you can debug problems more easily.

This is an example of the generated log:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
* Found bundle for host http2-push.io: 0x56193881ae40 [can multiplex]\n
* Connected to http2-push.io (216.239.38.21) port 443 (#0)\n

> GET /css/style.css HTTP/2\r\n
Host: http2-push.io\r\n
User-Agent: Symfony HttpClient/Curl\r\n
Accept-Encoding: deflate, gzip\r\n
\r\n

< HTTP/2 200 \r\n
< content-type: text/css\r\n
< content-encoding: gzip\r\n
< content-length: 1805\r\n
< etag: "0CqJow"\r\n
< \r\n

In PR #31831 we added a new cancel() method so you can cancel responses at any moment.

In PR #31976 and PR #32104 we improved the integration of the component with HTTPlug, another popular library to make HTTP requests. The Symfony HttpClient component is now interoperable with three different abstractions for HTTP clients: Symfony Contracts, PSR-18 and HTTPlug v1 and v2.

In PR #32231 we added support for NTLM authentication:

1
2
3
4
$client = HttpClient::create([
    'auth_ntlm' => 'username:password',
    // ...
]);

In PR #32290 we added a new toStream() method to cast responses to regular PHP streams:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$response = $client->request('GET', 'https://...');
$content = $response->toStream();

// alternatively, you can use this code:
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpClient\Response\StreamWrapper;

$client = HttpClient::create();
$response = $client->request('GET', 'https://...');
$streamResource = StreamWrapper::createResource($response, $client);

Contributed by
Ruben Jacobs
in #32565.

In PR #32565 we improved the buffer configuration option. In previous Symfony versions this was a boolean option. In Symfony 4.4 you can also pass a PHP closure (which must return a boolean value) to enable buffering conditionally:

1
2
3
4
5
6
7
$response = $client->request('GET', 'https://...', [
    'buffer' => function (array $headers): bool {
        // some logic here to decide if we want to buffer or not

        return true; // or return false;
    },
]);

Contributed by
Peter Schultz
in #34216.

In PR #34216 we improved the json configuration option. In previous Symfony versions, this option only allowed passing arrays or objects implementing JsonSerializable. In Symfony 4.4 you can pass any value which can be passed to json_encode(), which includes scalar values and classes with public properties:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Book
{
    public $title = '...';
    public $author = '...';
    // ...
}

$response = $client->request('PUT', 'https://...', [
    'json' => $book,
]);

Contributed by
Thomas Calvet
in #32807.

In PR #32807 we added a new configuration option called max_duration to define the maximum execution time allowed for the whole request + response process. Set it to 0 to not define any time limit:

1
2
3
$response = $client->request('GET', 'https://...', [
    'max_duration' => 21.7,
]);

Comments

I'm wondering how this compares to guzzle. Is there any advantage in Symfony HttpClient or are there fundamental differences?
I think httpclient everything better than guzzle except asynchronous requests.
I've already switched all our projects from guzzle to HttpClient. This improvements shows that it was a good choice.
@Michel K. Do you have any open-source projects to share? For inspiration, what and how needs to be changed
Login with SymfonyConnect to post a comment