Added JsonMockResponse

Thomas Calvet
Contributed by Thomas Calvet in #50044

The HttpClient component provides some utilities to test HTTP requests and responses using a MockHttpClient that returns MockResponse objects. In Symfony 6.3 we've introduced the JsonMockResponse utility class to mock JSON responses:

1
2
3
4
5
6
7
8
9
10
11
12
// BEFORE
use Symfony\Component\HttpClient\Response\MockResponse;

new MockResponse(
    json_encode(['foo' => 'bar']),
    ['response_headers' => ['content-type' => 'application/json']]
);

// AFTER
use Symfony\Component\HttpClient\Response\JsonMockResponse;

new JsonMockResponse(['foo' => 'bar']);

Configure Extra Options

Roman Andreev
Contributed by Roman Andreev in #48797

The extra option passed to the request() method of the HttpClient component allows to define additional configuration, such as cURL options. In Symfony 6.3 you can also define those extra options when configuring the HttpClient.

This way, you can configure cURL options such as certificates once and use them in all requests made with that HTTP client:

1
2
3
4
5
6
7
8
9
10
11
12
13
// this example shows how to configure these options when using
// PHP config format; but it also works with YAML and XML
return static function (FrameworkConfig $frameworkConfig): void {
    $httpClient = $frameworkConfig->httpClient();
    $httpClient->defaultOptions([
        'extra' => ['curl' => ['foo' => 'bar']]
    ]);

    $httpClient->scopedClient('some_client')
        ->baseUri('https://some.uri')
        ->header('Accept', 'application/json')
        ->extra(['curl' => ['foo' => 'bar']]);
}

TLS v1.2 by default

Nicolas Grekas
Contributed by Nicolas Grekas in #50274

In Symfony 6.3 we've added a new crypto_method option to the HttpClientInterface so you can define the minimum TLS version to accept when making requests. We've also set its default value to the PHP constant STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, which corresponds to TLS v1.2.

This makes the client more secure by default. (Note that TLS v1.2 is available since 2008 and that all major browsers disabled support for TLS < 1.2 in 2020.)

Multiple Retry URIs

Benjamin Zaslavsky
Contributed by Benjamin Zaslavsky in #49809

Retrying failed requests is one of the features that provides the HttpClient component to handle failed requests due to network issues or temporary server errors. In Symfony 6.3 we've improved this feature to allow defining multiple base URIs that are selected alternatively when retrying the requests:

1
2
3
4
5
6
$response = $client->request('GET', 'foo-bar', [
    'base_uri' => [
        'http://a.example.com/', // first request will use this base URI
        'http://b.example.com/', // if first request fails, the second base URI will be used
    ],
]);

File Upload Improvements

Nicolas Grekas
Contributed by Nicolas Grekas in #49911

When uploading data with the HttpClient component, the data is encoded by default as application/x-www-form-urlencoded. If you wanted to submit a form with file uploads, it was your responsibility to encode the body according to the multipart/form-data content-type.

In Symfony 6.3 we've improved this situation and now you can upload one or more files using multipart/form-data as follows:

1
2
$fileHandle = fopen('/path/to/the/file' 'r');
$client->request('POST', 'https://...', ['body' => ['the_file' => $fileHandle]]);

By default, this code will populate the filename and content-type with the data of the opened file, but you can configure both with the PHP streaming configuration:

1
2
stream_context_set_option($fileHandle, 'http', 'filename', 'the-name.txt');
stream_context_set_option($fileHandle, 'http', 'content_type', 'my/content-type')

Add Support for URI Templates

Thomas Calvet
Contributed by Thomas Calvet in #49302

URI templates, defined in the RFC 6570, describe a range of URLs via some variable parts. For example, http://example.com/{username}/ uses a variable in the URL path and http://example.com/search{?q,lang} uses two variables in the query string part of the URL.

In Symfony 6.3 you can use these URI templates with a new UriTemplateHttpClient():

1
2
3
4
5
6
7
8
9
$client = new UriTemplateHttpClient();

// This request will result on querying http://example.org/users?page=1
$client->request('GET', 'http://example.org/{resource}{?page}', [
    'vars' => [
        'resource' => 'users',
        'page' => 1,
    ],
]);

You can even configure variables that will be replaced globally in all URI templates of your application:

1
2
3
4
5
6
# config/packages/framework.yaml
framework:
    http_client:
        default_options:
            vars:
                - secret: 'secret-token'
Published in #Living on the edge