@plinthjs/http-client
v0.1.0
Published
Mason HTTP client over global fetch with retries and a fake (the Illuminate Http client equivalent).
Maintainers
Readme
@plinthjs/http-client
A fluent HTTP client over the global fetch — the Mason equivalent of Laravel's
Illuminate\Http\Client. Supports a chainable "pending request" builder, JSON/form body
encoding, query serialization, base-URL joining, per-request timeouts (via AbortController),
and automatic retries on network errors and 5xx responses.
The fetch implementation is always injectable, so tests run entirely offline.
Usage
import { Http } from '@plinthjs/http-client'
// GET with query parameters
const res = await Http({ baseUrl: 'https://api.example.com' }).get('/users', { page: 2 })
if (res.successful()) {
const users = res.json<{ id: number; name: string }[]>()
}
// POST JSON with a bearer token
const created = await Http()
.withToken('secret-token')
.asJson()
.post('https://api.example.com/users', { name: 'Ada' })
// POST form-encoded
await Http().asForm().post('https://api.example.com/login', { email: '[email protected]', password: 'x' })
// Retry on 5xx / network error: 3 extra attempts, 100ms apart
const resilient = await Http().retry(3, 100).get('https://api.example.com/flaky')
// Throw on a non-2xx response
const ok = (await Http().get('https://api.example.com/thing')).throw()Response helpers
HttpResponse exposes status(), ok(), successful(), failed(), clientError(),
serverError(), json<T>(), text(), header(name), headers(), and throw() (which raises
HttpRequestError when the response failed, otherwise returns the response for chaining).
Testing with the fake
Inject FakeHttp (or fakeFetch) so no real request is ever made:
import { Http, FakeHttp } from '@plinthjs/http-client'
const fake = new FakeHttp()
fake.respond(
{ status: 200, body: { id: 1, name: 'Ada' } },
{ method: 'POST', urlContains: '/users' },
)
const client = Http({ fetch: fake.fetch })
const res = await client.post('https://api.example.com/users', { name: 'Ada' })
expect(res.json()).toEqual({ id: 1, name: 'Ada' })
expect(fake.lastRequest()?.method).toBe('POST')Use fake.sequence([...]) to return canned responses one per call (handy for retry tests), and
inject a no-op sleep so retry delays are instant:
const fake = new FakeHttp().sequence([{ status: 503 }, { status: 200, body: 'ok' }])
const client = Http({ fetch: fake.fetch, sleep: async () => {} })
const res = await client.retry(1).get('https://api.example.com/flaky')
expect(res.status()).toBe(200)
expect(fake.count()).toBe(2)