nette/http
Nette HTTP is a lightweight PHP library for handling HTTP requests and responses. It provides clean APIs for headers, cookies, sessions, URL parsing, file uploads, and response output, making it easy to build robust web applications and services.
Architecture fit
nette/http is not a Laravel package — it is the HTTP abstraction layer of the Nette Framework (Nette\Http\Request, Response, Session, Url, RequestFactory). It ships no service provider, no facade, no config file, and does not implement PSR-7/PSR-15/PSR-17. Laravel already owns this entire surface through Illuminate\Http\Request (a Symfony HttpFoundation subclass). In architectural terms, this is a component-sourcing evaluation, not an integration. Roughly 80% of the package is redundant with Laravel and should be discarded; the remaining 20% is genuinely differentiated:
IPAddress + UrlValidator (v3.4.0) — the standout. An immutable IPv4/IPv6 value object with isPublic/isPrivate/isLoopback/isLinkLocal/isMulticast/isReserved, CIDR matching, and IPv4-mapped IPv6 normalization; paired with a configurable URL guard (scheme, port, host allow/blocklist, userinfo, optional DNS-resolved IP ranges) that returns resolved IPs for CURLOPT_RESOLVE pinning. Laravel's HTTP client has no first-class SSRF defense of this quality.Forwarded parsed into hops, trailing trusted proxies stripped, scheme/host taken from the same hop as the selected address, with a proxyHeaders: both|xForwarded|forwarded|none policy switch. This is materially more correct than typical hand-rolled X-Forwarded-For handling and directly relevant to audit logging and rate limiting behind ALBs/Cloudflare.SameSite enum, Partitioned/CHIPS, Max-Age precedence over expires, auto-Secure when SameSite=None, plus the sharp fix that explicit '' path/domain means host-only// while only null means "use default."Helpers::parseQualityList() and Url/UrlImmutable canonicalization, resolve(), removeDotSegments().Request::isFrom() with Sec-Fetch-* and a strict-cookie fallback for Safari < 16.4.Integration feasibility
Feasible only as a surgical, dependency-pinned extraction. The value classes (IPAddress, UrlValidator, Url, UrlImmutable, Helpers) are clean, strict-typed, and framework-agnostic — they can be consumed directly inside a Laravel service provider with no Nette container present. The Request/Response/Session/HttpExtension stack is not feasible and should not be attempted: Nette\Http\Session would compete with Laravel's session driver for session_start(), cookie params, and ID regeneration, and HttpExtension is bound to nette/di.
Technical risk
NOASSERTION. Nette packages are conventionally BSD-3-Clause, but the scanner could not confirm it and the file is not declared machine-readably. This is a hard gate for legal before any code lands..1 patch) made the DI extension trust only X-Forwarded-* by default and changed getRemoteAddress() to return null instead of a non-IP string. v3.4.0 raised the floor to PHP 8.3, removed UserStorage, and deprecated getRemoteHost() to always return null. Semver cannot be assumed; exact-version pinning and a changelog review per bump are mandatory.Dependents: 0 is almost certainly a resolver artifact — nette/http is a transitive dependency of nette/application, nette/forms, and Latte-adjacent stacks, so real-world footprint is far broader than reflected. The 2026-10-23 last-release date is a datum anomaly worth reconciling before treating the project as actively maintained on that cadence.nette/di, nette/utils, and Tracy (SessionPanel even emits Latte-like templates). Consuming only the value objects avoids this entirely.Key questions
NOASSERTION at v3.4.1, or do we require a resolved SPDX identifier and attribution text?Forwarded vs X-Forwarded-*, and who is authoritative for the client IP — the LB, Cloudflare, or the app?Partitioned cookies, or is SameSite=Lax sufficient?Nette\ directly?Stack fit
Do not replace Laravel's HTTP kernel. Position nette/http as an internal hardening library behind a thin Acme\HttpGuard adapter:
IPAddress + UrlValidator registered as a singleton, exposed as OutboundUrlGuard::validate(string $url): ResolvedTarget. Wire it into a Guzzle middleware and a Laravel HTTP client macro so every outbound user-influenced request is vetted, with the resolved IPs handed to CURLOPT_RESOLVE to close DNS-rebinding.RequestFactory::setProxy() semantics as a specification, implemented against Illuminate\Http\Request via a TrustedProxyResolver (or, more cheaply, reuse the class directly by constructing it from $_SERVER in a middleware and storing the trusted result on the request). Align with Laravel's existing TrustProxies middleware rather than running both.UrlImmutable for redirect-target canonicalization and open-redirect allowlisting; Helpers::parseQualityList() if we need ranked Accept-* negotiation for content endpoints.Nette\Http\Request, Response, Session, HttpExtension, SessionPanel, FileUpload. Laravel covers all of these; adopting them creates dual sources of truth for cookies and sessions.Migration path
There is nothing to migrate — this is net-new capability layered onto an unchanged Laravel stack. The real "migration" is retiring ad-hoc SSRF checks (regex host denylists, filter_var + gethostbyname snippets) scattered across jobs and controllers in favor of one guard. Inventory those first; each is a defect ticket that justifies the adoption.
Compatibility
Nette\ boundary, which the adapter contains.nette/di compilation pass. Register manually in a service provider.Sequencing
IPAddress/UrlValidator behave correctly against a corpus of SSRF payloads (http://127.0.0.1, [::1], 169.254.169.254, 0x7f000001, decimal-encoded IPs, DNS-rebinding harness). Success = blocks all, zero false positives on our known-good outbound hosts.Acme\HttpGuard package — pinned nette/http:3.4.1, no nette/di, guard service + Guzzle middleware + feature flag defaulting off.Maintenance
Low code footprint, but a real version-pinning obligation. Given that v3.4.1 shipped breaking behavior in a patch, treat every upgrade as a minor-change review: read the changelog, diff the IPAddress/UrlValidator/Url public surface, re-run the SSRF corpus. Budget roughly one engineer-day per bump and expect two to four bumps a year based on the observed cadence. Renovate/Dependabot should be configured to pin exactly and open a PR rather than auto-merge. Bus factor is concentrated in a small maintainer group outside our hiring profile — the adapter boundary is the mitigation, not documentation.
Support
No commercial support, no SLA, no Laravel-community answer base. Escalation path is GitHub issues on a 489-star repo. Internal ownership must be explicit: name a single owning team and a secondary. The upside is that the components we consume are small, pure, and fully unit-testable, so we can fork or vendor a pinned copy if upstream stalls — a credible contingency that most third-party dependencies do not offer.
Scaling
Effectively free at runtime — the value objects are immutable, stateless, and per-request allocation is negligible. The one scaling concern is DNS: UrlValidator with DNS range-checking enabled performs resolution per validation, which adds latency and creates a dependency on resolver throughput. Mitigate with a short-TTL cache keyed on hostname, a bounded resolution timeout, and per-endpoint concurrency limits so a burst of user-supplied URLs cannot exhaust the resolver or stall the queue workers. Horizontal scaling is unaffected — no shared state, no sessions, no disk.
Failure modes
CURLOPT_RESOLVE pinning is not optional. This is the single most likely way the integration is deployed incorrectly.X-Forwarded-* from a trusted proxy unless proxyHeaders: forwarded|both) is safer than its predecessor but will silently break any stack whose LB emits RFC 7239 Forwarded. Symptom: wrong client IPs in audit logs and rate limiters, or spoofable values if the trust boundary is set too wide.getRemoteAddress() returning null instead of a non-IP string. If we mirror that contract in the resolver, any code doing $ip string concatenation or DB insert without a null check will throw or persist empty values. Audit all IP consumers before rollout.Nette\Http\Session alongside Laravel's driver — headers already sent, session_status() conflicts, cookie param mutation after activation. Enforce with a static-analysis rule banning Nette\Http\Session and Nette\Http\Response imports.composer update could pull a release requiring a PHP version above our fleet baseline and fail at deploy. CI must run composer why-not php / platform checks on the lockfile.Ramp-up
Bimodal. The value classes are a half-day for a mid-level Laravel engineer — good docblocks, strict types, small surface. The Nette DI/culture layer (HttpExtension, Tracy panels, Latte templates in SessionPanel, $initialization semantics) is a multi-week context switch with no transferable value to a Laravel codebase, which is precisely why the integration approach must exclude it. Onboarding artifact: the internal adapter package's README plus the SSRF payload test corpus should be sufficient to make the dependency legible without any Nette background. Net recommendation: adopt narrowly (SSRF guard), reject broadly (request/response/session), gated on license resolution and PHP 8.3 confirmation.
How can I help you explore Laravel packages today?