calliostro/spotify-client
A PHP client for the Spotify Web API that simplifies authentication and access to Spotify data. Framework-agnostic and easy to drop into Laravel or any PHP project, it wraps API endpoints in a clean, developer-friendly interface for building music-powered applications.
This package wraps Guzzle/Laravel HTTP client calls with rate-limit-aware retry handling. The v1.0.1 release is a maintenance/CI release — it does not introduce breaking changes or new runtime features — so the onboarding path is unchanged.
Install and discover the config.
composer require <vendor>/<package>
php artisan vendor:publish --tag=<package>-config
The published config is the first file to read: it exposes max_retries, backoff, and rate-limit knobs. Check composer.json requirements for the supported matrix (PHP 8.1–8.6, Guzzle 7 or Guzzle 8), which matches what CI now explicitly tests.
Register the middleware. Attach the package middleware to the Guzzle handler stack, or to a named Laravel HTTP client. Confirm the middleware is ordered after logging/history middleware so retries are visible in your HTTP logs.
First use case.
Point it at a single flaky third-party API: set max_retries to a small number, enable rate limiting, and issue a request through the instrumented client. Watch for the expected Retry-After/backoff behaviour before rolling it out across all clients.
Http::withOptions(...)) and set retry/rate-limit values on that client. Different upstreams have very different tolerances, and a single global max_retries will either be too aggressive or too timid.max_retries of 0 is a legitimate configuration for non-idempotent endpoints. v1.0.1 adds a unit test covering exactly this case, so you can rely on it as a documented “fail fast” mode rather than a loophole.max_retries low (2–3) unless the endpoint is known-safe.RateLimited/redis queue middleware so retries happen at the HTTP layer and at the job layer without duplicating effort. Ensure the job’s own retry count accounts for the HTTP retries it will consume.Http::fake + sequence. Assert both the happy path and the retry path:
Http::fake([
'api.example.com/*' => Http::sequence()
->push(['error' => 'rate limited'], 429, ['Retry-After' => '1'])
->push(['ok' => true], 200),
]);
Then assert the number of recorded requests and that the final response succeeded.max_retries.max_retries = 0 is not “unlimited”. It disables retries. The new test in v1.0.1 formalises this behaviour; don’t assume 0 or null means “retry forever”.POST/PATCH without an idempotency key can duplicate side effects. Use max_retries = 0 for non-idempotent calls, or restrict retries to connection errors/5xx where the server almost certainly did not process the request.Retry-After handling. Honour server-provided delays where present, but cap them — a misbehaving upstream can return an absurd value and stall workers. Check whether your config exposes a maximum delay; if not, wrap or subclass the backoff strategy.max_retries to 1 and enable Guzzle’s debug option to see the raw exchange. If retries “don’t happen”, confirm the exception/status is in the package’s retryable set — a 4xx other than 429 is typically excluded by design.composer.json metadata. Re-run your test suite if you rely on Guzzle 8, since it is now a first-class supported target rather than an untested combination.How can I help you explore Laravel packages today?