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

Lib Rest Client Common Laravel Package

paysera/lib-rest-client-common

This package supplies the shared abstractions behind Paysera's PHP REST client libraries: HTTP transport, request signing/authentication, response decoding, error and exception mapping, and reusable data mappers, helping integrations stay consistent, testable, and maintainable.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the release with Composer and confirm you are on 2.8.0 or later:
    composer require <vendor>/<package>:^2.8
    
  2. Look first at two classes:
    • ClientFactoryAbstract — the base factory you extend to build Guzzle clients.
    • GuzzleMiddlewareInterface — the new contract for injectable Guzzle middleware.
  3. Start with one concrete API client. Create a factory subclass for the service you call most often, then add one middleware (auth or logging) through the new injection path rather than hand-building a Guzzle stack.

Minimal first use case:

use Vendor\Package\ClientFactoryAbstract;
use GuzzleHttp\Client;

class BillingClientFactory extends ClientFactoryAbstract
{
    protected function baseUri(): string
    {
        return config('services.billing.base_uri');
    }

    protected function defaultHeaders(): array
    {
        return [
            'Accept' => 'application/json',
        ];
    }
}

// Bind it once in a service provider.
$this->app->singleton(BillingClientFactory::class);

// Inject the factory, not a pre-built client, where you need it.
public function __construct(private BillingClientFactory $factory) {}

$client = $this->factory->make();

The first practical win in 2.8.0 is that middleware no longer needs to be wired manually every time you construct a client. Implement GuzzleMiddlewareInterface once and inject it into the factory.

Implementation Patterns

Middleware as a first-class unit

Implement the new interface for cross-cutting concerns:

use Vendor\Package\GuzzleMiddlewareInterface;
use Psr\Http\Message\RequestInterface;

class AddCorrelationId implements GuzzleMiddlewareInterface
{
    public function __invoke(callable $handler): callable
    {
        return function (RequestInterface $request, array $options) use ($handler) {
            return $handler(
                $request->withHeader('X-Correlation-Id', (string) Str::uuid()),
                $options
            );
        };
    }
}

Then inject it through the factory’s middleware configuration rather than wrapping the client after construction. This keeps the middleware stack consistent across every client the factory produces.

Compose middleware per client, not globally

Use separate factory subclasses or factory configuration for different upstream services. A payments client usually needs retry, idempotency, and strict timeouts; a reporting client may only need logging. Keeping middleware scoped to the factory avoids accidentally applying auth middleware to unrelated hosts.

Typical split:

  • AuthMiddleware — token or HMAC signing.
  • RetryMiddleware — only for idempotent requests.
  • LogMiddleware — request/response logging with redaction.
  • CorrelationMiddleware — trace IDs propagated to upstream services.

Inject the factory, resolve the client late

Prefer injecting ClientFactoryAbstract subclasses into services and jobs, then calling the factory when the client is needed. This lets middleware and config be resolved from the container at request time and makes testing easier. Avoid binding a fully constructed GuzzleHttp\Client as a singleton unless the client is truly stateless and config-independent.

Laravel integration

  • Bind factories in a service provider, usually as singletons.
  • If the package exposes a config array for middleware, publish it and register middleware class names there so deployments can toggle logging without code changes.
  • Use Laravel’s HTTP client only for simple cases; use this package when you need explicit Guzzle middleware control, streaming, or custom handler stacks.

Testing pattern

Use Guzzle’s MockHandler and HandlerStack in tests, and assert that your middleware is present in the stack:

$mock = new MockHandler([new Response(200, [], '{"ok":true}')]);
$stack = HandlerStack::create($mock);
$stack->push(new AddCorrelationId());

$client = new Client(['handler' => $stack]);

For factory-level tests, resolve the factory from the container and assert the produced client sends the expected headers or retries as configured.

Gotchas and Tips

  • Middleware order matters. Guzzle middleware is stack-based and generally runs in reverse order of pushing. If auth headers must exist before logging, verify the order the factory applies them. The new injection feature may append middleware in a defined order; check the factory implementation rather than assuming.
  • Don’t mutate a shared client. If a factory returns a singleton client and middleware captures request-specific state, you can leak data between requests. Prefer per-request client creation or ensure middleware is stateless.
  • Watch constructor signatures after upgrading. 2.8.0 adds middleware injection to ClientFactoryAbstract. If you subclass the factory and override its constructor without calling parent::__construct(), injected middleware may be silently skipped.
  • Config caching. If middleware is registered through Laravel config, run php artisan config:clear during debugging. Cached config can make it look like your new middleware class is not being picked up.
  • Interface compatibility. Implement GuzzleMiddlewareInterface exactly as defined by the package. Guzzle’s own MiddlewareInterface is similar but not necessarily interchangeable; type-hint the package contract where the factory expects it.
  • Retries need idempotency checks. Do not add retry middleware globally through the factory. Scope it to clients and methods where replaying the request is safe.
  • Logging redaction. Middleware that logs full requests will capture authorization headers and tokens. Redact Authorization, cookies, and signed query parameters before writing to logs.
  • Extension points. If the factory’s middleware list is not sufficient, override the factory’s client-building method and push additional middleware onto the HandlerStack. Keep custom stack manipulation in one subclass rather than scattering it across services.
  • Version pinning. Because this release changes the factory contract surface, pin to ^2.8 and run your integration tests against the new middleware injection path before rolling out broadly.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package