From f0239d8ce0de01bb5c9ac356881bd0f8754749f6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 29 Jan 2025 16:01:25 +0100 Subject: [PATCH 1/2] [HttpClient] Fix retrying requests with Psr18Client and NTLM connections --- .../Component/HttpClient/CurlHttpClient.php | 4 ++ .../Component/HttpClient/HttplugClient.php | 39 ++++++++++++++----- .../Component/HttpClient/Psr18Client.php | 39 ++++++++++++++----- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Component/HttpClient/CurlHttpClient.php b/src/Symfony/Component/HttpClient/CurlHttpClient.php index 67a6c1dddd5d8..ba3191c37c340 100644 --- a/src/Symfony/Component/HttpClient/CurlHttpClient.php +++ b/src/Symfony/Component/HttpClient/CurlHttpClient.php @@ -236,6 +236,10 @@ public function request(string $method, string $url, array $options = []): Respo } if (!\is_string($body)) { + if (isset($options['auth_ntlm'])) { + $curlopts[\CURLOPT_FORBID_REUSE] = true; // Reusing NTLM connections requires seeking capability, which only string bodies support + } + if (\is_resource($body)) { $curlopts[\CURLOPT_INFILE] = $body; } else { diff --git a/src/Symfony/Component/HttpClient/HttplugClient.php b/src/Symfony/Component/HttpClient/HttplugClient.php index 8e1dc1c4cb9e3..e6e4f20d50121 100644 --- a/src/Symfony/Component/HttpClient/HttplugClient.php +++ b/src/Symfony/Component/HttpClient/HttplugClient.php @@ -224,23 +224,42 @@ private function sendPsr7Request(RequestInterface $request, ?bool $buffer = null { try { $body = $request->getBody(); + $headers = $request->getHeaders(); - if ($body->isSeekable()) { - try { - $body->seek(0); - } catch (\RuntimeException) { - // ignore - } + $size = $request->getHeader('content-length')[0] ?? -1; + if (0 > $size && 0 <= $size = $body->getSize() ?? -1) { + $headers['Content-Length'] = [$size]; } - $headers = $request->getHeaders(); - if (!$request->hasHeader('content-length') && 0 <= $size = $body->getSize() ?? -1) { - $headers['Content-Length'] = [$size]; + if (0 <= $size && $size < 1 << 21) { + if ($body->isSeekable()) { + try { + $body->seek(0); + } catch (\RuntimeException) { + // ignore + } + } + + $body = $body->getContents(); + } else { + $body = static function (int $size) use ($body) { + if ($body->isSeekable()) { + try { + $body->seek(0); + } catch (\RuntimeException) { + // ignore + } + } + + while (!$body->eof()) { + yield $body->read($size); + } + }; } $options = [ 'headers' => $headers, - 'body' => static fn (int $size) => $body->read($size), + 'body' => $body, 'buffer' => $buffer, ]; diff --git a/src/Symfony/Component/HttpClient/Psr18Client.php b/src/Symfony/Component/HttpClient/Psr18Client.php index a2a19236e8f67..8bca6f770177b 100644 --- a/src/Symfony/Component/HttpClient/Psr18Client.php +++ b/src/Symfony/Component/HttpClient/Psr18Client.php @@ -88,23 +88,42 @@ public function sendRequest(RequestInterface $request): ResponseInterface { try { $body = $request->getBody(); + $headers = $request->getHeaders(); - if ($body->isSeekable()) { - try { - $body->seek(0); - } catch (\RuntimeException) { - // ignore - } + $size = $request->getHeader('content-length')[0] ?? -1; + if (0 > $size && 0 <= $size = $body->getSize() ?? -1) { + $headers['Content-Length'] = [$size]; } - $headers = $request->getHeaders(); - if (!$request->hasHeader('content-length') && 0 <= $size = $body->getSize() ?? -1) { - $headers['Content-Length'] = [$size]; + if (0 <= $size && $size < 1 << 21) { + if ($body->isSeekable()) { + try { + $body->seek(0); + } catch (\RuntimeException) { + // ignore + } + } + + $body = $body->getContents(); + } else { + $body = static function (int $size) use ($body) { + if ($body->isSeekable()) { + try { + $body->seek(0); + } catch (\RuntimeException) { + // ignore + } + } + + while (!$body->eof()) { + yield $body->read($size); + } + }; } $options = [ 'headers' => $headers, - 'body' => static fn (int $size) => $body->read($size), + 'body' => $body, ]; if ('1.0' === $request->getProtocolVersion()) { From b647cdf329619449a126d8c6d8ca8cb62c2f5122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20J=2E=20Garc=C3=ADa=20Lagar?= Date: Tue, 4 Feb 2025 11:02:47 +0100 Subject: [PATCH 2/2] Prevent empty request body stream in HttplugClient and Psr18Client This prevents adding `Content-Length` and `Transfer-Encoding` headers when sending a request with an empty body using CurlHttpClient --- src/Symfony/Component/HttpClient/HttplugClient.php | 6 ++++-- src/Symfony/Component/HttpClient/Psr18Client.php | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpClient/HttplugClient.php b/src/Symfony/Component/HttpClient/HttplugClient.php index e6e4f20d50121..dad01dcc89c8e 100644 --- a/src/Symfony/Component/HttpClient/HttplugClient.php +++ b/src/Symfony/Component/HttpClient/HttplugClient.php @@ -227,11 +227,13 @@ private function sendPsr7Request(RequestInterface $request, ?bool $buffer = null $headers = $request->getHeaders(); $size = $request->getHeader('content-length')[0] ?? -1; - if (0 > $size && 0 <= $size = $body->getSize() ?? -1) { + if (0 > $size && 0 < $size = $body->getSize() ?? -1) { $headers['Content-Length'] = [$size]; } - if (0 <= $size && $size < 1 << 21) { + if (0 === $size) { + $body = ''; + } elseif (0 < $size && $size < 1 << 21) { if ($body->isSeekable()) { try { $body->seek(0); diff --git a/src/Symfony/Component/HttpClient/Psr18Client.php b/src/Symfony/Component/HttpClient/Psr18Client.php index 8bca6f770177b..5ab4a8d3ce41d 100644 --- a/src/Symfony/Component/HttpClient/Psr18Client.php +++ b/src/Symfony/Component/HttpClient/Psr18Client.php @@ -91,11 +91,13 @@ public function sendRequest(RequestInterface $request): ResponseInterface $headers = $request->getHeaders(); $size = $request->getHeader('content-length')[0] ?? -1; - if (0 > $size && 0 <= $size = $body->getSize() ?? -1) { + if (0 > $size && 0 < $size = $body->getSize() ?? -1) { $headers['Content-Length'] = [$size]; } - if (0 <= $size && $size < 1 << 21) { + if (0 === $size) { + $body = ''; + } elseif (0 < $size && $size < 1 << 21) { if ($body->isSeekable()) { try { $body->seek(0); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy