http

← All adapters

http<T, R>(options: HttpOptions<T>): Destination<T, HttpResult<R>>

Make HTTP requests. Returns a Destination adapter that works with both .to() and .enrich().

Current support: Routecraft currently exports http() only as an outbound/client adapter for making HTTP requests.

Planned inbound support: Routecraft does not yet ship an inbound HTTP source/server adapter. The planned design is shown in Planned inbound/server HTTP support below and may change before implementation.

With .enrich() (merge result into body):

// Static GET request - result merged into body
.enrich(http({ 
  method: 'GET',
  url: 'https://api.example.com/users'
}))

// Dynamic URL based on exchange data
.enrich(http({ 
  method: 'GET',
  url: (exchange) => `https://api.example.com/users/${exchange.body.userId}`
}))

// Custom aggregator to control merge behavior
.enrich(
  http({ url: 'https://api.example.com/profile' }),
  (original, result) => ({
    ...original,
    body: { ...original.body, profileData: result.body }
  })
)

With .to() (side-effect or body replacement):

.to(http(...)) always invokes the http() adapter. When the adapter returns an HttpResult, .to() replaces the exchange body with that result. The first example below is a fire-and-forget pattern in intent only (the code does not read the response), but at runtime the body is still replaced by the HttpResult. To merge or preserve the original exchange body, use .enrich() with an aggregator instead of .to(http(...)).

// Fire-and-forget intent (code does not read the response); body is still replaced by HttpResult at runtime
.to(http({
  method: 'POST',
  url: 'https://api.example.com/webhook',
  body: (exchange) => exchange.body
}))

// http() returns HttpResult; .to() replaces exchange body with it
.to(http({ 
  method: 'GET',
  url: 'https://api.example.com/transform' 
}))
// Body is now the HttpResult (status, headers, body). Use .enrich() with an aggregator to merge or preserve the original body.

// With query parameters
.enrich(http({
  url: 'https://api.example.com/search',
  query: (exchange) => ({ q: exchange.body.searchTerm, limit: 10 })
}))

Options:

FieldTypeDefaultRequiredDescription
methodHttpMethod'GET'NoHTTP method to use
urlstring | (exchange) => string--YesTarget URL (string or derived from exchange)
headersRecord<string,string> | (exchange) => Record<string,string>{}NoRequest headers
query`Record<string,stringnumberboolean> | (exchange) => Query`{}
bodyunknown | (exchange) => unknown--NoRequest body (JSON serialized when not string/binary)
throwOnHttpErrorbooleantrueNoThrow when response is non-2xx
timeoutMsnumber--NoRequest timeout in milliseconds

Returns: HttpResult object with status, headers, body, and url

Planned inbound/server HTTP support planned

Tentative source signature: http({ path, method, ...options }).

// Simple webhook endpoint
.id('webhook-receiver')
.from(http({ path: '/webhook', method: 'POST' }))

// Multiple methods on same path
.id('data-api')
.from(http({ path: '/api/data', method: ['GET', 'POST', 'PUT'] }))
OptionTypeDefaultRequiredDescription
pathstring'/'NoURL path to mount
methodHttpMethod | HttpMethod[]'POST'NoAccepted HTTP methods

Exchange body: { method, url, headers, body, query, params }. The final exchange becomes the HTTP response; no explicit .to() step is required.

Response behavior:

  • The final exchange is returned to the HTTP client. If the final body is an object with optional fields { status?: number, headers?: Record<string,string>, body?: unknown }, those fields are used to build the response.
  • If status or headers are not provided, Routecraft returns the body with 200 status and no additional headers.
  • For serialization and setting Content-Type, use a formatting step in your capability (e.g., a .transform(...) that sets appropriate headers).