Skip to content

API ReferenceHttpClient

HttpClient

Internal HTTP client that wraps native fetch with typed methods, automatic serialization, and path parameter resolution.

2 min readboth modes

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:

ts
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:

ts
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)
ts
// 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:

ts
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/42

Streaming

When stream: true is set in the endpoint options, the response data is a ReadableStream:

ts
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:

ts
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.