vectorface/whip
Whip is a lightweight PHP library for reliably determining a client’s real IP address, even behind proxies, load balancers, and CDNs. It supports IPv4/IPv6, trusted proxy headers, Cloudflare, and multi-proxy setups, helping PHP and Laravel apps log, rate-limit, and secure requests accurately.
Architecture fit: Vectorface/whip is a single-purpose, framework-agnostic PHP utility for resolving a client's real IP address when the application sits behind proxies, load balancers, or CDNs (Cloudflare, Incapsula, etc.). It is not a Laravel package and ships no service provider, facade, or config file. That is acceptable for what it does — it wraps proxy-header parsing behind a small object API — but a TPM should position it as a low-level library invoked from a custom middleware rather than a drop-in Laravel feature. Note that Laravel already provides TrustProxies and Request::getClientIp() for standard X-Forwarded-* chains; whip's differentiated value is vendor-specific header detection (e.g., CDN headers that do not use the standard forwarding scheme). If the estate is behind a plain ALB/nginx, this package is largely redundant.
Integration feasibility: Very high. composer require vectorface/whip is the entire integration, and the API is small enough to wrap in a single middleware or a Request::macro. No native Laravel binding exists, so the team owns the glue code (a one-time few hours), but there is no migration, no schema, and no config surface to learn.
Technical risk: The dominant risk is versioning maturity, not code quality. The package is pre-1.0 (v0.x), so semver stability is explicitly not guaranteed and minor bumps can carry breaking changes. v0.5.0 is exactly that: it raises the PHP floor to 8.0, which is a hard incompatibility for any application still on PHP 7.4. Secondary risk is bus factor — a small maintainer base (Vectorface, now with a first-time contributor in @francislavoie) — mitigated by the package's small surface area, which makes vendoring or a fork cheap if needed. The security-relevant risk is inherent to the problem domain: incorrect trust configuration (trusting proxy headers from untrusted sources) enables client IP spoofing, which corrupts rate limiting, audit logging, and geo/IP allowlists. That risk belongs to our configuration, not to the library, but it must be called out.
Key questions:
TrustProxies cannot resolve? If not, why add the dependency?Stack fit: Clean fit for a Laravel 9+/PHP 8.0+ stack. The library has no framework coupling, so it composes naturally into a global or route middleware that runs after the real proxy has terminated the connection and before anything consumes $request->ip(). It coexists with Laravel's own TrustProxies; in practice you would use one or the other for a given traffic path, not both, to avoid two competing sources of truth for the client IP.
Migration path: Additive and non-disruptive. Install the package, introduce a middleware that resolves the IP via whip, and have it set the resolved value on the request (or via a request macro) so downstream consumers — throttling, logging, audit — read from one canonical accessor. Keep Laravel's TrustProxies in place until the new path is validated in staging, then retire or narrow it. No data migration, no downtime.
Compatibility: Requires PHP 8.0+ as of v0.5.0. For applications on 7.4, pin to v0.4.0 and treat it as frozen; do not expect security or feature backports. Given the pre-1.0 version, pin an exact version and review every minor bump as a potential breaking change.
Sequencing:
TrustProxies in one pilot app; if native handling suffices, stop.Maintenance: Low and bounded. One small dependency, no transitive baggage of note, no runtime services, no scheduled work. The real maintenance burden is the trusted-proxy allowlist, which changes as the CDN's ranges change and needs an owner and a refresh cadence.
Support: The package is community-maintained with a small contributor base and no commercial support. Our team must be prepared to own it: read the source (it is small), pin versions, and be ready to fork or vendor. Escalation to upstream is best-effort.
Scaling: Negligible cost — header parsing is O(number of headers) per request, stateless, no I/O, no caching layer required. It does not affect horizontal scale.
Failure modes:
v0.6.0 altering the API with no major-version signal. Mitigate with exact version pinning and reading changelogs before bumps.TrustProxies and whip disagreeing during migration. Mitigate by cutting over in one step per app.Ramp-up: Very low. A developer unfamiliar with the package can read the whole API in well under an hour. The domain knowledge required — proxy chains, X-Forwarded-For ordering, CDN header semantics — is the real learning curve, and it is knowledge the team should have anyway. Budget roughly a day of engineer time per application including staging validation, plus a half-day for the trusted-range automation if it does not already exist.
How can I help you explore Laravel packages today?