slick/http
Slick HTTP is a lightweight HTTP package for PHP, offering a clean API for building requests and handling responses. It integrates easily into Laravel or standalone projects and keeps external API calls simple, testable, and maintainable.
Release delta (v4.0.2). A patch release that sets UrlEncodedParser as the parser for multipart/form-data. Two facts matter more than the change itself: (1) the package now visibly exposes a pluggable body-parser layer, an abstraction not described in the prior assessment; (2) the change was shipped as a patch despite altering runtime behavior for a content type. Neither shifts the strategic verdict, but both refine the risk picture and the verification plan.
Positioning. slick/http remains a framework-agnostic PSR-7 HTTP foundation — message objects, a middleware-driven request runner, session handling, body parsing, and an HTTP client. It is not a Laravel package and does not target Laravel's HTTP kernel: no service provider, no facade, no published config, no HttpFoundation bridge. The new parser registry confirms the design intent — this is a self-contained HTTP stack that owns the request lifecycle end to end, including how request bodies are interpreted. That is precisely the layer Laravel already owns.
Architecture fit. Laravel builds on Symfony HttpFoundation (Request/Response) with its own kernel, router, middleware pipeline, session manager, cookie encryption, and HTTP client. Slick/Http occupies the same layer of the stack rather than a layer above it.
| Component | Fit with a Laravel app | Assessment |
|---|---|---|
| PSR-7 message implementations | Low–moderate | Laravel already bridges to/from PSR-7 via symfony/psr-http-message-bridge; a second implementation creates type-mixing friction |
Middleware server (Slick\Http\Server) |
Very low | Competing request runner. Adopting it bypasses Laravel's kernel and forfeits routing, DI, auth, validation, and the ecosystem |
| Body parser layer (new in v4.0.2) | Very low | Direct overlap with Symfony ParameterBag/InputBag and PHP's own $_POST/$_FILES population. In a Laravel app, multipart bodies are decoded by the SAPI before your code runs — a second parser is either dead code or a source of disagreement |
| Session handling | Very low | Overlaps SessionManager, cookie encryption (APP_KEY), CSRF, and driver abstraction. Two session systems in one app is a defect generator |
| HTTP client | Low | Laravel's Http facade (Guzzle-backed) already covers this with retries, fakes, and testing assertions |
| PSR-7 messages as standalone DTOs | Moderate | Still the one defensible use: a library that must emit/consume PSR-7 without pulling in Laravel or Guzzle |
On the parser change specifically. Routing multipart/form-data to a class named UrlEncodedParser is a semantic mismatch worth understanding before anything else. multipart/form-data (RFC 7578) is a boundary-delimited, per-part structure with its own content-type and disposition headers; application/x-www-form-urlencoded (RFC 1867/WHATWG URL) is a flat key=value&key=value string with percent-encoding. They are not interchangeable. Either the class name is a misnomer for a broader parser, or multipart bodies will be handled by logic written for a different encoding. The likely practical consequence is a silent failure mode: malformed or partially-parsed bodies rather than an exception, because lenient parsers rarely reject. This is a question to answer by reading the code, not by reading the changelog.
Integration feasibility. Unchanged: technically possible in narrow slices, not feasible as a foundation. No first-party Laravel path exists, and the parser layer adds surface area that overlaps native PHP behavior rather than complementing it.
Technical risk.
| Risk | Severity | Rationale |
|---|---|---|
| Adoption / bus factor | High | Still 0 stars, 0 dependents (unverified for this release). You would be the only meaningful consumer; issues are likely to go unanswered. "The Slick Team" in the notes is a mild positive signal — organizational identity rather than an anonymous handle — but it is not evidence of headcount, a security policy, or an on-call rotation |
| Multipart parsing correctness (new) | Medium–high | UrlEncodedParser handling multipart/form-data is a structural mismatch. Verify with real boundary-delimited payloads (file parts, multiple fields, quoted boundaries, repeated field names, UTF-8 filenames). Check whether unsupported bodies are rejected or silently mangled |
| Semantic versioning discipline (new) | Medium | A behavior change to request parsing shipped in a patch release (v4.0.1 → v4.0.2). If the team treats behavioral changes as patch-level, ^4.0 is not a safe constraint and every update requires a diff review |
| PSR-7 conformance | Medium | Header normalization, stream seekability, upload handling, immutability. Must be verified with php-http/psr7-integration-tests, not assumed |
| Middleware contract | Medium | Confirm PSR-15 compliance versus a proprietary signature; the latter forfeits the PSR-15 middleware ecosystem |
| Session security | High | Cookies, fixation, ID regeneration, storage. Security-critical code competing with a heavily audited implementation |
| Maintenance continuity | High | v4.0.1 → v4.0.2 within a short window shows the repo is alive and shipping. It does not show resourcing, a SECURITY.md, or a disclosure process |
| License | None | MIT is clean and compatible |
| Performance | Low–medium | PSR-7 immutability implies allocation per mutation; a hand-rolled runner plus a body parser has no measured baseline under Laravel-style load |
Key questions to resolve before any commitment.
multipart/form-data in v4.0.2 — is UrlEncodedParser misnamed, or does multipart actually flow through URL-encoded logic? What happens to a multipart body with file parts?php-http/psr7-integration-tests suite, including streams and uploads?SECURITY.md presence.Stack fit. Assume Laravel 10–12 on PHP 8.2+. There is no first-party path: no provider, no config publish, no container bindings. Any use is manual wiring inside a package or a narrow module. The v4.0.2 parser layer does not change this — it adds an abstraction that maps to nothing in Laravel, because Laravel inherits already-decoded request bodies from PHP and Symfony.
| Layer | Native Laravel | slick/http |
Verdict |
|---|---|---|---|
| Request/response | Symfony HttpFoundation | PSR-7 | Bridge only, don't replace |
| Middleware | Laravel pipeline | Slick Server |
Non-overlapping, don't mix |
| Body parsing | PHP $_POST/$_FILES + Symfony InputBag |
Parser registry | Redundant in-app; relevant only if you never touch a real SAPI |
| Sessions | SessionManager + drivers |
Own implementation | Do not co-exist |
| HTTP client | Http facade (Guzzle) |
Own client | Redundant |
| Message DTOs | Arrays / value objects | PSR-7 | Viable niche |
Migration path — three options, ranked. The release does not change the ranking.
symfony/psr-http-message-bridge + nyholm/psr7 for PSR-7 interop, Laravel's Http client, Laravel sessions. Zero risk, zero integration cost.4.0.2 exact rather than ^4.0, given the patch-level behavior change), and enforce a boundary so the types never leak into application code. Do not adopt the parser layer — it has no in-app use case.Compatibility. Unchanged materially: verify PHP bounds, PSR-7 v1 vs v2 return-type signatures, and interface collisions with already-installed Psr\Http\Message types. Two new items — confirm the parser registry does not depend on a specific PSR-7 stream implementation, and confirm behavior under Octane/Swoole, where php://input is readable once and a hand-rolled parser must not assume re-readable streams.
Sequencing (if Option B is pursued).
multipart/form-data body with two text fields and a small file part, feed it to the v4.0.2 parser, and diff the parsed output against expectation. Also feed it a URL-encoded body and a JSON body to check strictness. This is now the cheapest test with the highest chance of ending the evaluation.php-http/psr7-integration-tests, record pass/fail per test.nyholm/psr7 and measure the diff. A trivial swap means the dependency is doing nothing you can't get elsewhere.Maintenance. Still 0 stars and 0 dependents, so maintenance transfers almost entirely to your team. The v4.0.1 → v4.0.2 cadence is a genuine positive: the project ships. But the release also demonstrates that behavioral changes land in patch versions, which raises the ongoing cost of staying current — you cannot rely on the version constraint to protect you. Budget for diff review on every bump, plus forking and patching if adopted.
Support. Expect no community, documentation depth limited to source, and slow or absent issue responses. The changelog style (one line, no rationale) means the why behind behavioral changes is not documented — you will read code to answer questions the release notes should answer. Internal documentation of your integration is mandatory.
Scaling. For narrow PSR-7 DTO use, negligible. For kernel, session, or parser replacement, unmeasured: PSR-7 immutability allocates per header mutation, session scalability depends on the configured backend, and body parsing now adds a full-buffer read step whose memory profile on large uploads is unknown. Under Octane/Swoole, persistent workers amplify any static or request-scoped state bugs, and single-read input streams become a real constraint. None of this is benchmarkable without investment.
Failure modes.
| Failure | Impact | Mitigation |
|---|---|---|
Multipart body mis-parsed by UrlEncodedParser (new) |
Silent data loss, dropped file parts, malformed payloads reaching business logic | Day-1 multipart spike with real boundary payloads; prefer native PHP decoding in-app |
| Behavioral change in a patch release (new) | Unnoticed parsing change after composer update |
Pin exact version or internal fork; diff-review every bump |
| PSR-7 conformance gap (streams, headers) | Subtle serialization or upload bugs in production | Integration test suite in CI |
| Session security flaw (fixation, unsigned cookie) | Account takeover | Do not use; retain Laravel sessions |
| Middleware signature divergence from PSR-15 | Middleware non-portable and unreusable | Confirm contract before adoption |
| Maintainer abandonment | No security patches | Fork and own, or avoid |
| Duplicate session/HTTP client/parser stacks | Split-brain auth state, inconsistent retries and body semantics | Enforce one implementation per concern |
| Duplicate PSR-7 implementations in the container | Type errors at injection boundaries | Pin one PSR-7 library app-wide |
Ramp-up. The API surface remains small: a senior PHP engineer is productive in one to two days, plus a half-day for the PSR-7 immutability model. The parser layer adds little learning cost but demands judgment — you must decide whether its multipart behavior is trustworthy, which requires reading the implementation rather than the docs. The dominant cost is still the absence of Laravel's scaffolding: routing, DI, auth, validation, error rendering, and testing helpers must be rebuilt or worked around if Option A is chosen.
Bottom line. Unchanged recommendation — Option C, no adoption — with Option B (isolated PSR-7 message usage, exact version pin) as the only defensible exception. The v4.0.2 release does not create a use case; it adds a low-fit component and one new verification item that should be run first, because a multipart parser routing through URL-encoded logic is the kind of defect that fails quietly in production.
How can I help you explore Laravel packages today?