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

Rest Client Laravel Package

innmind/rest-client

innmind/rest-client is a simple PHP REST client for consuming HTTP APIs. It offers a clean interface for building requests, handling responses, and integrating remote REST services into Laravel or plain PHP applications without boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check: this package is archived, has no dependents, and 2 stars. Treat it as vendored source you own, not a maintained dependency. Before writing code, clone the repo and read src/ and tests/ — the tests are the actual documentation.

Install (pin hard):

composer require innmind/rest-client:"^<known-good-version>"

You will likely also need a transport implementation from the Innmind ecosystem (e.g. a PSR-7/HTTP transport such as innmind/http-transport-curl or innmind/stream) and its companions (innmind/url, innmind/immutable). Pin every one of them in composer.json; the transitive version constraints are the first thing that will bite you.

Where to look first, in order:

  1. README.md — usually a terse example, not a tutorial.
  2. src/Client.php (or equivalent Client interface) — the contract you'll program against.
  3. src/Server.php, src/Definition/, src/Server/Builder.php — how resources and endpoints are declared.
  4. tests/ — the only reliable source of realistic usage.
  5. The Innmind transport package you chose — that's where timeouts, headers, and debugging live.

First use case — wrap a single read endpoint. Build the narrowest possible slice: one transport, one client, one GET, one DTO. Example shape (verify against the actual signatures in src/):

use Innmind\Rest\Client\Server;
use Innmind\Rest\Client\Server\Builder;
use Innmind\Url\Url;

$server = Builder::of()
    ->withUrl(Url::of('https://api.example.com'))
    // register resources/definitions here
    ->build();

$response = $server->read(/* resource name, id, options */);

Get that returning a typed value before touching writes, pagination, or auth. The package's value is the typed resource/definition model; if you skip it and hand-roll URLs, you're paying the dependency cost for nothing.

Implementation Patterns

Keep Innmind types at the boundary. The library exposes its own value objects (URLs, definitions, resources). Don't let Innmind\Rest\Client\* leak into your domain or controllers. Wrap it in a small adapter that accepts and returns plain PHP DTOs:

interface OrdersApi {
    public function find(string $id): Order;
    public function create(NewOrder $order): OrderId;
}

final class InnmindOrdersApi implements OrdersApi
{
    public function __construct(private Server $server) {}

    public function find(string $id): Order
    {
        $resource = $this->server->read('orders', $id);
        return Order::fromArray($resource->content()->toArray());
    }
}

That adapter is what makes the package replaceable when you inevitably migrate off it.

Declare resources centrally, not per call. Use the builder/definition layer to describe each resource once (name, URL pattern, allowed methods, field mapping). This is the package's main leverage over Guzzle: endpoint schema lives in one place and call sites stay declarative.

Compose, don't inherit. If the package supports middleware/handler wrapping around the transport, put cross-cutting concerns there:

  • Auth header injection
  • Correlation IDs / request logging
  • Retry with backoff (only on idempotent verbs)
  • Response decoding

Keeping these in the transport/middleware layer means your adapter stays thin and testable.

Test against a fake transport. Point the client at an in-memory or stub transport that returns canned responses. Because the client is transport-agnostic, this is cheap and fast — and essential given there's no upstream test suite you can rely on for your usage.

Error handling — normalize early. Convert library exceptions into a small set of your own: NotFound, ValidationFailed, RateLimited, TransportError. The Innmind exception hierarchy is fine internally but shouldn't be your public contract.

Pagination and collections: define a small iterator/page abstraction in your adapter. Do not scatter page/offset logic across call sites; the definition layer rarely models pagination well, so own it yourself.

Auth: there's no OAuth/token-refresh story here. Implement token acquisition outside the client and inject the resulting header via middleware. If you need refresh-on-401, that belongs in your middleware, not the resource definitions.

Gotchas and Tips

Archived = frozen. No security patches, no PHP 8.x/9 compatibility fixes, no PSR evolution. Audit composer.json PHP constraints and transitive deps before adopting. If the package pins an old innmind/* generation, you may be stuck upgrading other parts of your stack — check composer why-not early.

Version pinning is the top source of pain. The Innmind ecosystem moves together. Use exact versions or tight ranges, commit composer.lock, and run composer update --dry-run in CI to see when things would drift. One loose constraint can pull incompatible innmind/immutable or innmind/url versions.

The functional/typed style is a learning cliff. Method names, value objects, and error semantics differ significantly from Guzzle/PSR-18. Budget a day for one endpoint. If the team isn't comfortable, the abstraction cost can exceed the benefit — a thin Guzzle wrapper plus OpenAPI-generated DTOs may be the better call here.

Sparse docs mean tests are the spec. When behavior is unclear (what happens on 404, how query params are encoded, what content() returns for empty bodies), write a failing test against a fake transport and read the implementation. Don't guess from method names.

Debugging transports is where you'll spend time. Enable logging at the transport layer (PSR-3 logger, or log raw PSR-7 requests/responses in a decorator) rather than inside the client. You need to see the exact URL, headers, and body being emitted — the definition layer can silently alter them.

Serialization is your job. Don't assume request bodies are auto-JSON-encoded or responses auto-decoded. Centralize encode/decode in the adapter: one place, one content-type assumption, one set of tests.

Extension points to prefer:

  • A custom transport/handler decorator for retries, logging, auth.
  • A custom resource definition or builder subclass for non-standard URL shapes.
  • Your own adapter interface for everything else.

Avoid subclassing internal Server/Client classes directly — there's no maintainer to keep those extension points stable.

Exit strategy. Because the package is archived, write the adapter interface first and keep it free of Innmind types. That way, replacing InnmindOrdersApi with a Guzzle- or PSR-18-based implementation is a single-class change, not a rewrite. Given the maintenance risk, this is non-negotiable.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route