8000 bug #58562 [HttpClient] Close gracefull when the server closes the co… · symfony/symfony@9eea677 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9eea677

Browse files
bug #58562 [HttpClient] Close gracefull when the server closes the connection abruptly (discordier)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [HttpClient] Close gracefull when the server closes the connection abruptly | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | License | MIT curl will return `-1.0` for `CURLINFO_CONTENT_LENGTH_DOWNLOAD` since [7.19.4](https://curl.se/libcurl/c/CURLINFO_CONTENT_LENGTH_DOWNLOAD.html) if not known (means not specified by the server response). When handling data for empty responses, this will cause us to compare `0.0` (`CURLINFO_SIZE_DOWNLOAD`) with `-1.0` (`CURLINFO_CONTENT_LENGTH_DOWNLOAD`) and thus error out with SSL error 0 then (which means normal close). We therefore now explicitly allow to download 0 bytes, when no size has been indicated. I'm unsure how to add tests here and also unsure what's the lowest version to be affected. I don't think this affects BC, as the usecase to expect to get an error for an empty response seems very unlikely. I tried to come up with a reproducer but failed as I can only reproduce it via HTTPS in my application. Stacktrace: ``` In Stream.php line 266: [RuntimeException] Unable to read stream contents: OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 0 for "https://[redacted]/api". Exception trace: at /project/vendor/nyholm/psr7/src/Stream.php:266 Nyholm\Psr7\Stream::Nyholm\Psr7\{closure}() at n/a:n/a trigger_error() at /project/vendor/symfony/http-client/Response/StreamWrapper.php:129 Symfony\Component\HttpClient\Response\StreamWrapper->stream_read() at n/a:n/a stream_get_contents() at /project/vendor/nyholm/psr7/src/Stream.php:270 Nyholm\Psr7\Stream->getContents() at /project/vendor/nyholm/psr7/src/StreamTrait.php:23 Nyholm\Psr7\Stream->__toString() at /project/src/ApiClient823/Generated/Endpoint/VersionVersion.php:57 [...] ``` The same request via `curl -v`: ``` curl -v https://[redacted]/api * Trying [redacted]... * Connected to [redacted] ([redacted]) port 8006 (#0) * ALPN: offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * subject: CN=[redacted] * start date: Aug 22 00:39:02 2024 GMT * expire date: Nov 20 00:39:01 2024 GMT * subjectAltName: host "[redacted]" matched cert's "[redacted]" * issuer: C=US; O=Let's Encrypt; CN=R10 * SSL certificate verify ok. * using HTTP/1.x > GET /api HTTP/1.1 > Host: [redacted] > User-Agent: curl/7.88.1 > Accept: */* > * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing < HTTP/1.1 401 No ticket < Cache-Control: max-age=0 < Connection: close < Date: Mon, 14 Oct 2024 13:52:18 GMT < Pragma: no-cache < Server: [redacted] < Expires: Mon, 14 Oct 2024 13:52:18 GMT < * Closing connection 0 * TLSv1.3 (OUT), TLS alert, close notify (256): ``` Commits ------- 8c26ace [HttpClient] Close gracefull when the server closes the connection abruptly
2 parents 1b7d8b3 + 8c26ace commit 9eea677

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

src/Symfony/Component/HttpClient/Response/CurlResponse.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ private static function perform(ClientState $multi, ?array &$responses = null):
327327
}
328328

329329
$multi->handlesActivity[$id][] = null;
330-
$multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) ? null : new TransportException(ucfirst(curl_error($ch) ?: curl_strerror($result)).sprintf(' for "%s".', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL)));
330+
$multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) || (curl_error($ch) === 'OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 0' && -1.0 === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) && \in_array('close', array_map('strtolower', $responses[$id]->headers['connection']), true)) ? null : new TransportException(ucfirst(curl_error($ch) ?: curl_strerror($result)).sprintf(' for "%s".', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL)));
331331
}
332332
} finally {
333333
$multi- 3A1E >performing = false;

0 commit comments

Comments
 (0)
0