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

Zttp Laravel Package

kitetail/zttp

Zttp is a simple, elegant HTTP client for PHP built on Guzzle, offering a fluent, Laravel-style API for GET, POST, JSON, form, and header requests with minimal boilerplate. Chain methods like withHeaders, asJson, and withoutRedirecting, and install easily via Composer.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit Zttp is a thin, static-style fluent facade over Guzzle (guzzlehttp/guzzle ^6.x), exposing a tiny surface: verb methods (get/post/put/patch/delete), header/auth builders (withHeaders/withToken/withBasicAuth), body encoders (asJson/asFormParams), timeout/retry, and a ZttpResponse value object. Architecturally it is a convenience layer, not infrastructure — it owns no transport, no connection pooling, no async model. That is good for adoption (a single Composer dependency, no service provider required, optional facade alias) and bad for longevity (nothing to sustain it once upstream Guzzle moves).

The decisive architectural fact is that Zttp's design was absorbed into first-party Laravel as Illuminate\Support\Facades\Http (Laravel 7+). For any Laravel 7 or newer application, Zttp is a redundant dependency duplicating a shipped capability with a near-identical API. Zttp only has a defensible slot on Laravel ≤6 or in non-Laravel PHP 7.x code.

Integration feasibility Low effort, high governance cost. Integration is composer require kitetail/zttp plus an optional alias; a developer can be productive in under an hour. The blockers are not integration blockers, they are portfolio blockers:

  • Guzzle 6 pin. Guzzle 6 is end-of-life. If any other dependency in the tree (AWS SDK, Stripe, Socialite, mail transports, internal SDKs) requires Guzzle 7, resolution fails or forces --ignore-platform-reqs-style workarounds. composer why-not guzzlehttp/guzzle 7 is the first command to run.
  • PHP version ceiling. A 2019 release will not have been validated against PHP 8.1/8.2/8.3 semantics; deprecation noise and dynamic-property/typed-signature issues are plausible.
  • Provenance gap. The supplied metadata reports Repository: unknown. We cannot verify source, CI, release signing, or issue history from the package record alone. For a package that will sit in the request path of every outbound call, that is a supply-chain finding, not a footnote.

Technical risk

  • Abandonment (high, certain). Last release 2019-06-10; no security-response process. Every future Guzzle advisory becomes our incident, resolved only by forking or constraint-overriding.
  • Retry correctness (high, unverified). Retrying non-idempotent verbs (post, patch) can duplicate side effects on the remote system. Additionally, Guzzle request bodies are streams: a retry against a consumed, non-rewound stream can send an empty body or throw. This must be proven, not assumed.
  • Error semantics (medium, unverified). Confirm whether 4xx/5xx throw a Guzzle RequestException or return a populated ZttpResponse. Either behavior is fine, but call sites that assume the other one silently swallow failures.
  • Escape-hatch depth (medium). Determine whether a custom Guzzle client/handler stack can be injected. Without it we cannot use MockHandler in tests, set proxies/custom CAs, or attach tracing middleware — all of which we will need.
  • Concurrency (medium). No first-class async/Pool exposure. Fan-out patterns degrade into sequential N+1 outbound calls, which shows up as latency, not as an error.

Key questions

  1. What is our Laravel/PHP baseline by service, and does Guzzle 6 resolve cleanly there today?
  2. Can we inject a Guzzle client or handler stack (testing, tracing, proxies, mTLS)?
  3. Do we retry non-idempotent verbs, and are request bodies rewindable across retries?
  4. Do 4xx/5xx throw or return a response object, and do all call sites check .isOk()/.status()?
  5. Is there an approved escape hatch for Guzzle options (verify, sink, connect_timeout, proxy)?
  6. Do we need concurrent outbound calls in any current or planned flow?
  7. Are we willing to own a fork, or is the correct answer "adopt Http and delete this"?

Integration Approach

Stack fit Strong on Laravel ≤6 and standalone PHP 7.x. Weak-to-negative on Laravel 7+ (the Http facade is the same API, first-party, Guzzle-7-based, actively maintained) and unproven on PHP 8.1+. Treat Zttp as a legacy-compatible shim, never as a forward-looking choice.

Migration path The API similarity is the single biggest asset here: Zttp:: → Http:: is largely mechanical.

  • Zttp::withHeaders([...])->post($url, $payload) → Http::withHeaders([...])->post($url, $payload)
  • ->asJson() semantics shift (Zttp content-type setter vs Laravel's body/headers behavior) — audit each call site rather than find-replacing.
  • ->timeout($s) maps directly; ->retry($times, $sleep) maps to Laravel's retry($times, $sleepMs, $when) with a seconds-to-milliseconds change.
  • ZttpResponse → Illuminate\Http\Client\Response: ->status(), ->body(), ->json(), ->header() are near-equivalent; ->isOk() must be re-verified. For non-Laravel code, migrate to Guzzle 7 directly behind a small internal client class rather than to a new third-party wrapper.

Compatibility Two independent compatibility checks, both mandatory before commitment:

  1. Dependency graph — Guzzle 6 vs 7 across the full tree, including transitive dev dependencies.
  2. Runtime matrix — PHP 8.1/8.2/8.3 with deprecation-as-error enabled in CI.

If either fails, Zttp is not a viable option regardless of its ergonomics.

Sequencing

  1. Inventory (grep -rn "Zttp::" and composer why-not guzzlehttp/guzzle 7) — get call-site count and blast radius. This is a half-day task and produces the go/no-go.
  2. Contain — introduce an internal App\Support\Http boundary that current Zttp call sites route through. This is cheap because the API is ~10 methods, and it decouples the migration decision from the code.
  3. Replace behind the boundary — implement with Laravel Http (Laravel 7+) or Guzzle 7 (plain PHP). Do not rewrite call sites twice.
  4. Prove behavior parity — contract tests against recorded fixtures; explicitly test retry-on-POST, timeout, non-2xx handling, and large/streamed bodies.
  5. Remove the dependency — drop the Composer requirement and the facade alias. Only if steps 3–4 are blocked should we fork and re-publish (bump Guzzle constraint, add CI + advisory watching), which is a 1–2 day cost plus permanent ownership.

Operational Impact

Maintenance Effectively zero upstream maintenance and zero upstream accountability. The package is a convenience API over a transport library that has since moved two major versions; ergonomics do not rot, but security posture does. Realistic operating models are (a) no fork: accept that Guzzle CVEs require a forced constraint override or a rushed migration during an incident, or (b) fork: own it, pin Guzzle 7, add CI and a dependency-review job. Neither is free; the honest TCO is "small quarterly cost plus an unbounded incident-shaped tail risk."

Support 1,668 stars is a popularity signal from the Laravel-6 era, not a support contract. Expect no response on issues, no docs beyond the README, and no backport policy. The compensating factor is that the API is small and idiomatic enough that any competent PHP developer can read the source in an afternoon. The internal-knowledge risk is low; the external-support risk is total.

Scaling For typical synchronous service-to-service calls, the Guzzle 6 cURL handler is fine — throughput and connection handling will not be the bottleneck. Two scaling caveats matter: (1) no exposed async/Pool primitive means request fan-out serializes, which is a latency problem that appears only under load; (2) if the client is instantiated per call rather than reused, connection reuse and keep-alive are lost. Both need to be measured, not reasoned about.

Failure modes Ranked by likely production impact:

  • Duplicate writes from retries on non-idempotent verbs.
  • Truncated retried bodies from consumed, non-rewound Guzzle streams.
  • Silent failures if 4xx/5xx return a response object and a caller forgets .isOk() — errors become empty payloads downstream.
  • Indefinite hangs where timeout/connect_timeout were not set; verify the default.
  • Dependency deadlock the day a mandatory security patch requires Guzzle 7.
  • Observability blind spot — no middleware hook means no distributed tracing, no structured outbound request logs, no per-dependency circuit breaking. Mitigations are cheap and worth doing even in the "keep it" scenario: enforce explicit timeouts, an .isOk() check at every call site (or a wrapper that throws), idempotency keys on retried POSTs, and a metrics/tracing shim around the boundary.

Ramp-up Developer ramp-up is measured in hours — the fluent API is genuinely self-documenting and arguably better than raw Guzzle. That is the package's real and only durable advantage, and it is precisely the advantage Laravel's Http facade now provides for free. Organizational ramp-up is where the cost sits: every new engineer must learn why this dependency exists, why it is unmaintained, and what the fork/override procedure is. That is permanent cognitive overhead carried by a package chosen for a temporary convenience.

TPM recommendation: treat Zttp as a migration target, not an adoption candidate. Stand it up behind an internal boundary only where it already exists, run the dependency-graph and PHP-matrix checks, and converge on first-party Http (Laravel 7+) or Guzzle 7 (plain PHP). Do not add new call sites.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource