Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Streams Laravel Package

guzzlehttp/streams

A lightweight PHP library for working with streams, offering object-oriented wrappers, lazy and buffered streams, filtering, limiting, and utility helpers. Once used by Guzzle to power HTTP request and response bodies, it remains useful for composing and manipulating stream data.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What this package actually is. guzzlehttp/streams is a low-level, ~1k-line library exposing a StreamInterface plus Stream, BufferStream, NoSeekStream, LazyOpenStream, AppendStream, PumpStream, and a Utils helper. It is not a Laravel package: there is no service provider, facade, config file, or Artisan surface. It has no application-level entry point a TPM would commission work against — it is infrastructure glue that appears in a composer.lock because something else depended on it.

Architecture fit. Poor as a deliberate addition, neutral as an inherited dependency. Laravel applications already have stream primitives at every layer that matters:

  • HTTP responses: Symfony\Component\HttpFoundation\StreamedResponse / BinaryFileResponse
  • HTTP client: GuzzleHttp\Psr7\Stream behind Laravel's Http facade
  • Filesystem: Flysystem stream resources (Storage::readStream() returns a PHP resource, not a stream object)

guzzlehttp/streams sits beside these, not inside them. The one place it historically mattered — as the stream implementation consumed by Guzzle 5/6 and PSR-7-era code — has been superseded by guzzlehttp/psr7, which vendors the same abstractions against psr/http-message. Any new code should target Psr\Http\Message\StreamInterface and guzzlehttp/psr7; adopting this package directly is a regression in architectural direction.

Integration feasibility. Mechanically trivial (composer require guzzlehttp/streams), strategically unattractive. Two hard constraints dominate:

  1. Archived — upstream is read-only. No releases, no CVE response, no PHP-version compatibility work.
  2. Interface duplication risk — installing it alongside guzzlehttp/psr7 yields two independent StreamInterface implementations in the autoloader. Any code doing instanceof checks or type-hinting one against the other will fail at runtime in ways that only appear on specific code paths (file uploads, S3 reads, streamed exports). This is the highest-probability defect a team would ship.

Technical risk. Rated on the dimensions that matter to a TPM:

Risk Severity Notes
Abandonment / no security patches High Archived; MIT lets you fork, but that is a permanent ownership cost
Type/interface collision with psr7 Medium-High Silent, path-dependent runtime failures
PHP 8.x compatibility Low-Medium Constraint permits PHP 8; simple code, but untested upstream since ~2016
Transitive-only dependency Medium Version pinning becomes fragile if a future Laravel/Guzzle upgrade drops it
Data-loss / correctness in stream handling Medium Non-seekable and detached-stream edge cases are poorly documented

Key questions to answer before any decision.

  1. Is this a direct or transitive dependency? (composer why guzzlehttp/streams)
  2. If transitive, which parent pulls it, and does that parent have a newer major that uses psr7 instead?
  3. Are we type-hinting GuzzleHttp\Stream\StreamInterface anywhere in first-party code, or only passing objects through?
  4. Has the security/SCA tooling flagged this as an unmaintained package, and is it already on an exception list?
  5. What is the actual business capability at stake — large-file proxying, S3 streaming, chunked downloads, log streaming? That determines whether this is a five-minute cleanup or a scoped migration.

The score (2.08) and 26.24 opportunity rating both point the same direction: low strategic upside, so the correct TPM posture is containment and eventual removal, not adoption or investment.

Integration Approach

Stack fit. For a Laravel 10/11 target on PHP 8.1+, this package is at best tolerated. Composer resolution normally succeeds because the constraint is permissive, but "installs" is not "supported." A TPM should treat successful installation as the start of the risk discussion, not the end of it.

Decision tree — the recommended sequencing for any Laravel codebase currently carrying this dependency:

  1. Inventory (½ day). Run composer why, composer depends, and grep for GuzzleHttp\Stream, StreamInterface, LazyOpenStream, PumpStream, AppendStream, NoSeekStream across app/, packages/, and any internal composer packages. Classify each hit as own code vs vendor transit.
  2. If transitive-only (most likely): no action beyond an SCA exception record. Pin the resolved version in composer.lock, add a note to the upgrade runbook, and let it ride until the parent library's next major bump removes it.
  3. If referenced in first-party code: replace, don't extend. Map GuzzleHttp\Stream\StreamInterface → Psr\Http\Message\StreamInterface, and GuzzleHttp\Stream\Stream::factory($resource) → GuzzleHttp\Psr7\Utils::streamFor($resource). The API surface is small and the mapping is nearly 1:1; expect 1–3 days per service for a typical codebase, dominated by test fixtures rather than production code.
  4. If the codebase needs new stream handling: do not use this package. Use guzzlehttp/psr7 (already present via the HTTP client) or raw PHP resources with Laravel's response()->stream() / response()->streamDownload().

Migration path and compatibility. The replacement is not a rewrite — psr7 implements the same PSR-7 contract with a maintained codebase, PHP 8 support, and an actual security process. The migration is a namespace and factory-call substitution plus a re-run of integration tests against real I/O (S3, local disk, chunked HTTP).

Sequencing constraints.

  • Do the interface-boundary audit before adding any new dependency that also ships a StreamInterface, or you will create the collision you are trying to avoid.
  • Land replacement work in the same release window as an existing Guzzle or psr7 upgrade; bundling avoids a second round of regression testing on HTTP and filesystem paths.
  • Do not schedule this alongside a Laravel major-version upgrade. Both touch the HTTP and filesystem layers, and a failure will be ambiguous to diagnose.

Explicit non-goals. Forking and vendoring the library, writing a compatibility shim between guzzlehttp/streams and psr7 types, or building a Laravel service provider wrapper around it. All three convert a small, bounded dependency problem into permanent maintenance overhead — the worst possible trade for a package rated this low on opportunity.

Operational Impact

Maintenance. Zero upstream. The archive is permanent; there will be no fix for a PHP 8.x deprecation, no PSR update, no CVE patch. The effective maintenance owner is your own team, whether or not anyone has been told. Cost is near-zero while the API keeps working, but it is an unhedged liability — the failure mode is "a PHP minor release deprecates a signature and a background job starts throwing" with no path to an upstream fix.

Support. Support burden falls entirely on internal staff or on the maintainer of whichever library pulls it in transitively. In an incident, the troubleshooting path is "read the source" — which is feasible here (small codebase, MIT), but is not a plan a TPM should accept for a service with a real SLA attached. Recommend adding this package to the SCA/allowlist with a written justification and a named owner, so that the exception is deliberate and auditable rather than accidental.

Scaling. Genuinely fine, and this is the strongest argument for leaving it alone where it already works. The abstraction's core value is memory-bounded I/O: php://temp spills to disk past a threshold (2 MB by default), so streaming a multi-GB file through Stream::factory(fopen(...)) costs constant memory rather than file size. For Laravel workloads involving S3 uploads/downloads, report exports, or proxying large media, the stream abstraction underneath is doing real work and the alternative (loading into a string) is what actually breaks. No concurrency, locking, or connection-pool concerns — streams are per-request resources.

Failure modes to instrument and alert on. These are the ones a TPM should expect the on-call rotation to eventually encounter:

Failure Symptom Mitigation
__toString() on a large stream PHP memory limit fatal, 500s under load Code review rule: never stringify a stream; stream or streamDownload() the response
Non-seekable stream re-read RuntimeException: Cannot rewind on retry logic Wrap in CachingStream or buffer before any retryable operation
Detached / closed stream Silent empty output, no exception Assert stream is readable before writing to it
php://temp disk fill Node disk pressure, degraded writes across the app Monitor sys_get_temp_dir() usage; set explicit temp path with capacity
psr7 interface mismatch instanceof returns false only on specific endpoints Integration tests that exercise real S3/disk paths, not mocks

The detach and non-seekable cases are the ones that produce silent wrong output rather than loud errors, which makes them the most expensive. Test coverage on stream paths matters more than usual here.

Ramp-up. Low — a competent PHP developer understands the abstraction in half a day, and the codebase is small enough to read end to end. The real ramp-up cost is not the library but the stream semantics the team must internalize (seekability, detachment, memory vs. disk buffering, backpressure). Budget roughly one engineer-day of onboarding for anyone who will own file-handling or streaming endpoints, and put the failure-mode table above in the team runbook rather than re-deriving it during an incident.

Net TPM recommendation. Contain, don't adopt. Confirm whether it is transitive (most likely) or first-party (unlikely); if first-party, migrate to guzzlehttp/psr7 bundled into the next HTTP-layer upgrade. Record an explicit SCA exception with a named owner, and revisit at the next framework major-version cycle. Do not fork, shim, or wrap it — the low score and modest 26.24 opportunity rating both indicate that engineering time is better spent elsewhere.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource