Skip to main content
The PHP SDK talks to Nexus through a PSR-18 ClientInterface and PSR-17 factories. It depends on the interfaces rather than on a concrete client, so it uses whichever HTTP stack your project already has - and does not install a second one alongside it.

Discovery

Pass nothing and php-http/discovery finds the implementation your project has installed:
If there is none, create() raises an error naming what to install.

Injecting your own

Pass your configured client to reuse its proxy settings, middleware and instrumentation for Nexus traffic too:
Each part falls back to discovery independently, so supplying only the client is fine. In Laravel this happens for you - the service provider takes the container’s PSR-18 binding when there is one.

Any implementation works

Both are verified on every commit. One CI job installs the package into an empty project and fails if any HTTP stack comes with it; another runs the SDK end to end against Symfony HttpClient with Guzzle absent.

What gets installed

Installing westyx/nexus brings 6 packages, about 1 MB:

Status codes

PSR-18 clients return 4xx and 5xx responses rather than throwing, and the SDK maps every status to a typed exception itself.
The exceptions to catch around SDK calls are WestyxNexus\Exceptions\NexusException and its subclasses, not your HTTP client’s - the SDK never lets an implementation-specific error type reach your code. See Error handling.
The mapping is shared by every endpoint, so a condition reports identically wherever it occurs: a 429 on an A/B evaluation carries its Retry-After and its quarantine details exactly as one on a sync does.

Redirects

A Nexus endpoint never redirects, and the SDK’s requests carry the API key, so the client must not follow a redirect to a server-chosen host. The SDK treats a 3xx it receives as an error.
Configure the client you pass (or the one discovery finds) to not follow redirects. Guzzle’s PSR-18 sendRequest() already does not; build Symfony HttpClient as new Psr18Client(HttpClient::create(['max_redirects' => 0])), since its PSR-18 client follows redirects by default and would replay the API key to the redirect target.
The SSE stream sets this itself (ext-curl, no CURLOPT_FOLLOWLOCATION).

Response size

Every response is read with a hard byte limit enforced while reading - 10 MB for a sync, 1 MB for everything else. Exceeding it raises a size error naming the limit, rather than handing a truncated document to the JSON parser.

Live updates are the exception

PSR-18’s sendRequest() returns a complete ResponseInterface, and whether the body is buffered before returning is left to the implementation. There is no standard way to request incremental delivery, so a buffering client would block forever on an endless event stream. connectStream() therefore uses ext-curl directly, which is also what gives it a real connection deadline and a liveness deadline. Without ext-curl it raises an actionable error and everything else, TTL polling included, works normally - losing live updates is a degradation, not a failure.