guzzlehttp/guzzle
Guzzle is a PHP HTTP client that makes sending HTTP requests simple and integrating with web services trivial. It supports sync and async requests, PSR-7 and PSR-18 interfaces, streaming uploads and downloads, middleware, and abstracts away the underlying transport.
Content-Length (including 0), chunked bodies decode as they arrive and must terminate at the last chunk, truncated/malformed chunked bodies are rejected, unsupported transfer codings are rejected, and gzip/deflate trailing-data rules match libcurl. This turns silent truncation into deterministic exceptions — a data-integrity decision for reporting, exports, invoices, webhooks, and ETL pulls. It also fixes bytes being delayed when they arrive with the headers, which affects time-to-first-byte on streamed responses.ResponseTransferException. That's the hook for retry/alerting policy that distinguishes "transfer died mid-body" from generic connection failure — but only if you update error handling and dashboards. Silence here creates a blind spot, not a crash.guzzlehttp/promises ^3.1 and guzzlehttp/psr7 ^3.2. Before committing, audit every package that pins older majors (PSR-7 implementations especially) and every place your own code touches promise helpers: Promise\Is is replaced by Promise\State for PHP 8.6. That's both a forward-compat signal for the PHP fleet (8.6 readiness) and a small but real code-change item.Promise\Is → Promise\State replacement, and transfer-exception handling to the audit list from the 7.14.1 review. The earlier "~2 dev-weeks, low risk" sizing still does not transfer to a major-version boundary.Content-Length boundaries, transfer-coding rejection, and deflate/gzip trailer parity is precisely the subtle libcurl-parity work you should not hand-roll. The package is doing it for you — which is also the argument for taking these releases rather than pinning.Adopt 8.3.0 if:
stream => true or custom handlers) for high-volume downloads, exports, or webhook ingestion — especially against third-party or flaky upstreams that occasionally truncate.guzzlehttp/psr7 ^3.2 and guzzlehttp/promises ^3.1 without conflicting pins, and have already committed to the 8.x line.Defer or look elsewhere if:
ResponseTransferException — you will silently swallow transfer failures.Verify before committing:
psr7 ^3.2 / promises ^3.1: all direct and transitive pins, and compatibility of whichever PSR-7 implementation you use.Promise\Is) in app code and in any vendored/first-party packages.Content-Length short and long; Content-Length: 0; unsupported transfer codings; gzip/deflate with trailing bytes; raw deflate.ResponseTransferException.For Executives: "8.3.0 changes the funding story. Everything valuable in 8.2.0 was locked behind a recent libcurl, so the upgrade was really a base-image-refresh decision with no payoff until that landed. 8.3.0 delivers value on the runtime we already have: the streaming download path now enforces the declared body length, rejects truncated or malformed responses instead of silently handing us partial data, and raises a specific exception for transfers that die mid-body — which is what lets us retry and alert correctly. It also brings PHP 8.6 readiness, but it raises our minimum versions of two supporting libraries, so it is a dependency review as well as a code change. Recommendation: fund 8.3.0 as a contained hardening release targeted at our streaming workloads, with clear targets on truncated-body incidents and retry accuracy, and keep the connection-cap plus base-image-refresh initiative separately scoped as before."
For Engineering:
"What changed in 8.3.0 — and it is not the same shape of change as 8.2.0: the libcurl 8.22.0 gate still applies to the cap+share feature, but the new work is runtime-independent. The stream handler now decodes chunked bodies incrementally, ends bodies at their declared Content-Length (including zero), rejects truncated/malformed chunked bodies, rejects unsupported transfer codings, matches libcurl on gzip/deflate trailing data and raw deflate, and fixes bytes arriving with headers being delayed. cURL errors 8 and 23 with a response are now ResponseTransferException. Dependency floors move to guzzlehttp/psr7 ^3.2 and guzzlehttp/promises ^3.1, and Promise\Is is replaced by Promise\State for PHP 8.6. What to do: (1) resolve dependencies and check PSR-7 implementation compatibility; (2) grep for Promise\Is; (3) build a behavior-diff test bed for the seven stream-handler cases above; (4) audit catch blocks and alerts for the new exception type; (5) run curl and stream handlers against the same upstreams to catch the 8.14+ semantics divergence if our libcurl is older; (6) re-run the 7.14.1 regression list — proxy credential parsing, integer CURLMOPT_PIPELINING, stream => true with custom handlers, NTLM + multiplexing. Ask: approval for a one-sprint 8.3.0 hardening spike with the stream-handler test bed as the deliverable."
For Developers: "8.3.0 tightens the stream handler to match libcurl — assume some previously 'working' upstreams will now throw. Handle the new type explicitly, and don't rely on lenient parsing:
use GuzzleHttp\Exception\ResponseTransferException;
try {
$response = $client->get($url, ['stream' => true]);
$body = $response->getBody()->getContents(); // ends at Content-Length, or throws
} catch (ResponseTransferException $e) {
// cURL 8 (couldn't resolve/connect after partial) or 23 (write error),
// plus truncated/malformed chunked bodies and over-length bodies.
// Retry or dead-letter here — do NOT fall through to a generic catch.
} catch (ConnectException | RequestException $e) {
// existing handling
}
Also: the body now stops at its declared Content-Length, including 0, so code that tolerated over-long or short reads must be fixed. Chunked bodies must end at the last chunk. Unsupported transfer codings are rejected. Gzip/deflate bodies with trailing data are rejected; raw deflate is accepted. And Promise\Is is gone in favour of Promise\State — grep before you upgrade, including vendored packages. Test the stream path against every upstream you don't control; the curl path may still be more permissive if our libcurl predates 8.14."
How can I help you explore Laravel packages today?