Overview
HttpClient is the low-level HTTP client at the core of Courier. It wraps the native fetch API and provides typed HTTP method functions (get, post, put, patch, del, head, options, query). You never create an HttpClient directly — it is created internally by executeRequest.
Internal class
HttpClient is used internally by Courier. Understanding it helps with debugging and writing the closure an endpoint passes to .via(), but you don't instantiate it yourself.
HTTP Methods
At definition time .via() hands its closure an HttpWire — a recorder that
captures which method and path the endpoint addresses. At request time the same
closure runs against an HttpClient bound to the source, whose six methods carry
the call out:
get: <T>(url?, variables?, options?) => Promise<HttpResponse<T>>
post: <T>(url?, variables?, options?) => Promise<HttpResponse<T>>
put: <T>(url?, variables?, options?) => Promise<HttpResponse<T>>
patch: <T>(url?, variables?, options?) => Promise<HttpResponse<T>>
del: <T>(url?, variables?, options?) => Promise<HttpResponse<T>>
head: <T>(url?, options?) => Promise<HttpResponse<T>>HttpResponse
Every method returns an HttpResponse wrapping status, headers, and typed data:
type HttpResponse<T = unknown> = {
status: number // HTTP status code
headers: Headers // Response headers
data: T // Parsed response body
}Variable Handling
How variables are sent depends on the HTTP method:
- GET, DELETE, HEAD — variables become search parameters
- POST, PUT, PATCH — variables become JSON body (or FormData if detected)
// GET: variables → search params
http.get("", { page: 1, limit: 10 })
// → GET /users?page=1&limit=10
// POST: variables → JSON body
http.post("", { name: "Jane", email: "jane@test.com" })
// → POST /users body: { name: "Jane", email: "jane@test.com" }
// FormData detected automatically
http.post("", formData)
// → POST /users body: FormData (multipart)Path Parameters
:param syntax in URLs is replaced with matching variable values. Remaining variables go to body or search params:
http.get(":id", { id: "123", include: "posts" })
// → GET /users/123?include=posts
http.put(":id", { id: "123", name: "Alice" })
// → PUT /users/123 body: { name: "Alice" }
http.get(":userId/posts/:postId", { userId: "1", postId: "42" })
// → GET /users/1/posts/42Streaming
When stream: true is set in the endpoint options, the response data is a ReadableStream:
endpoint.get(":channel/stream").variables<{ channel: string }>().response<ReadableStream>()Context
The Context object provides access to the incoming request for header forwarding. Its cookies are forwarded where the source or the endpoint names cookie:
type Context = {
req?: Request // Incoming request
res?: Response // Outgoing response
headers?: Headers // Headers to forward
}Error Handling
HttpClient converts HTTP error responses (status >= 400) into HTTPError objects with status, headers, and parsed data. Network errors produce HTTPError with status: 0.
Related
- HTTP Client Guide — in-depth usage patterns
- defineGroup — where endpoints describe the call they make
- HTTPError — error class thrown by HttpClient
- Types — all type definitions