HttpClient unstable
Provides the service used to run outgoing HTTP requests.
HttpClient executes immutable HttpClientRequest values and returns
HttpClientResponse values. Keeping HTTP behind this service lets programs,
tests, and generated API clients use the same request model without depending
on one concrete platform transport. This module includes request accessors,
constructors and layers, request and response transformations, status
filtering, retries, rate limiting, cookies, redirect handling, scoped request
abortion, and tracing support.
Accessors
Executes a DELETE request using the HttpClient service from the environment.
Signature
declare const del: (url: string | URL, options?: HttpClientRequest.Options.NoUrl) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient>Executes a prebuilt HttpClientRequest using the HttpClient service from the environment.
Signature
declare const execute: (request: HttpClientRequest.HttpClientRequest) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient>Executes a GET request using the HttpClient service from the environment.
Signature
declare const get: (url: string | URL, options?: HttpClientRequest.Options.NoUrl) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient>Executes a HEAD request using the HttpClient service from the environment.
Signature
declare const head: (url: string | URL, options?: HttpClientRequest.Options.NoUrl) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient>Executes an OPTIONS request using the HttpClient service from the environment.
Signature
declare const options: (url: string | URL, options?: HttpClientRequest.Options.NoUrl) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient>Executes a PATCH request using the HttpClient service from the environment.
Signature
declare const patch: (url: string | URL, options?: HttpClientRequest.Options.NoUrl) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient>Executes a POST request using the HttpClient service from the environment.
Signature
declare const post: (url: string | URL, options?: HttpClientRequest.Options.NoUrl) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient>Executes a PUT request using the HttpClient service from the environment.
Signature
declare const put: (url: string | URL, options?: HttpClientRequest.Options.NoUrl) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient>Executes a QUERY request using the HttpClient service from the environment.
Signature
declare const query: (url: string | URL, options?: HttpClientRequest.Options.NoUrl) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error.HttpClientError, HttpClient>Circuit Breaking
The default withCircuitBreaker classifier.
Details
- Failure: status 408, 500, 502, 503 or 504, returned or wrapped in a
StatusCodeError, and anyTransportErrororCause.TimeoutError. - Success: any other response, including other 4xx, since the dependency answered.
- Ignored: status 429 (left to
withRateLimiter),EncodeError,InvalidUrlError,DecodeError,EmptyBodyError, unknown typed errors and defects. HttpClient errors are typed, so a defect here is a bug in the caller.
When a cause holds several errors, a failure beats a success and a success
beats an ignored outcome. A failure carries the longest Retry-After it
saw. The result is an Effect only because parsing an HTTP-date
Retry-After reads Clock.
Gotchas
TransportError also covers client-side refusals, which count as failures.
Signature
declare function circuitBreakerClassifier<E>(exit: Exit<HttpClientResponse, E>): Effect<Outcome>Guards requests with a CircuitBreaker.
Details
Requests are keyed by origin unless key is set, and classified with
circuitBreakerClassifier unless classify is set. A rejected request
fails with CircuitBreakerError without reaching the wrapped client.
Apply it after withRateLimiter and retryTransient, so the breaker sees
one outcome per call and an open circuit skips the retry loop.
retryTransient never retries a CircuitBreakerError. A custom classify
can delegate the cases it doesn't handle to circuitBreakerClassifier.
Gotchas
- The breaker only sees the response headers. To count an error in the
body, lift it into the error channel below the breaker with
transformResponseand count it inclassify. withRateLimiterretries429without limit by default, which can hold the probe slot for minutes. Set itstimes.- A rejected request has no client span. The rejection fails the caller's span instead.
Example (Counting an error in the body as a failure)
This API answers 200 with { "status": "degraded" } when it is failing.
Signature
declare const withCircuitBreaker: { <E, R2 = never>(options: Options<E, R2>): <R>(self: With<E, R>) => With<E | CircuitBreakerError, R2 | R>; <E, R, R2 = never>(self: With<E, R>, options: Options<E, R2>): With<E | CircuitBreakerError, R | R2>;}Example Guarding an API in the recommended order
import { Effect, Layer, Ref, Schedule } from "effect"import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/http"import { CircuitBreaker, RateLimiter } from "effect/persistence"
const program = Effect.gen(function*() { const requests = yield* Ref.make(0) // A dependency that always answers 503. const unavailable = HttpClient.make((request) => Effect.as(Ref.update(requests, (n) => n + 1), HttpClientResponse.fromWeb(request, new Response(null, { status: 503 }))) )
const breaker = yield* CircuitBreaker.make({ tripPolicy: CircuitBreaker.consecutive(1), openDuration: "30 seconds" }) const client = unavailable.pipe( HttpClient.withRateLimiter({ limiter: yield* RateLimiter.RateLimiter, key: "inventory", limit: 100, window: "1 second", times: 3 }), HttpClient.retryTransient({ times: 2, schedule: Schedule.exponential("1 millis") }), HttpClient.withCircuitBreaker({ breaker }) )
// Three attempts, then the breaker records one failure and opens. yield* client.execute(HttpClientRequest.get("http://inventory.test/items")) // Rejected before the retry loop starts, so no further request is sent. const rejected = yield* Effect.flip(client.execute(HttpClientRequest.get("http://inventory.test/items")))
return [yield* Ref.get(requests), rejected._tag]}).pipe( Effect.scoped, Effect.provide(Layer.merge( CircuitBreaker.layerStoreMemory(), RateLimiter.layer.pipe(Layer.provide(RateLimiter.layerStoreMemory)) )))
await Effect.runPromise(program) // => [3, "CircuitBreakerError"]Example Counting an error in the body as a failure
import { Data, Effect, Exit, Option } from "effect"import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/http"import { CircuitBreaker } from "effect/persistence"
class Degraded extends Data.TaggedError("Degraded") {}
const degraded = HttpClient.make((request) => Effect.succeed(HttpClientResponse.fromWeb(request, Response.json({ status: "degraded" }))))
const program = Effect.gen(function*() { const breaker = yield* CircuitBreaker.make({ tripPolicy: CircuitBreaker.consecutive(1), openDuration: "30 seconds" }) const client = degraded.pipe( HttpClient.transformResponse(Effect.flatMap((response) => Effect.flatMap(response.json, (body) => typeof body === "object" && body !== null && "status" in body && body.status === "degraded" ? Effect.fail(new Degraded()) : Effect.succeed(response)) )), HttpClient.withCircuitBreaker({ breaker, classify: (exit) => Option.exists(Exit.findErrorOption(exit), (error) => error._tag === "Degraded") ? CircuitBreaker.failure() : HttpClient.circuitBreakerClassifier(exit) }) )
yield* Effect.flip(client.get("http://status.test/")) const state = yield* breaker.state("http://status.test") return state._tag}).pipe(Effect.scoped, Effect.provide(CircuitBreaker.layerStoreMemory()))
await Effect.runPromise(program) // => "Open"Constructors
Constructs an HttpClient from a low-level request runner.
Details
The runner receives the request, resolved URL, abort signal, and current fiber. The client wrapper handles URL construction failures, tracing and propagation, header redaction, and aborting non-scoped requests on interruption.
Signature
declare function make(f: (request: HttpClientRequest, url: URL, signal: AbortSignal, fiber: Fiber<HttpClientResponse, HttpClientError>) => Effect<HttpClientResponse, HttpClientError>): HttpClientConstructs an HttpClient.With from a preprocessing function and a postprocessing function.
Details
execute applies preprocessing to the request and then passes the resulting request effect to postprocessing.
Signature
declare function makeWith<E2, R2, E, R>(postprocess: (request: Effect<HttpClientRequest, E2, R2>) => Effect<HttpClientResponse, E, R>, preprocess: Preprocess<E2, R2>): With<E, R>Error Handling
Handles client failures with one or more matching _tag values and returns a transformed client.
Signature
declare const catchTag: { <K extends string | readonly [Tags<E>, Tags<E>], E, E1, R1>(tag: K, f: (e: ExtractTag<NoInfer<E>, K extends readonly [string, string] ? K[number] : K>) => Effect<HttpClientResponse, E1, R1>): <R>(self: With<E, R>) => With<E1 | ExcludeTag<E, K extends readonly [string, string] ? K[number] : K>, R1 | R>; <R, E, K extends string | readonly [Tags<E>, Tags<E>], R1, E1>(self: With<E, R>, tag: K, f: (e: ExtractTag<E, K extends readonly [string, string] ? K[number] : K>) => Effect<HttpClientResponse, E1, R1>): With<E1 | ExcludeTag<E, K extends readonly [string, string] ? K[number] : K>, R | R1>;}Handles client failures by matching their _tag values against a case map.
Signature
declare const catchTags: { <E, Cases extends { [K in string]: (error: Extract<E, { _tag: K; }>) => Effect<HttpClientResponse, any, any> } | { [K in string]: (error: Extract<E, { _tag: K; }>) => Effect<HttpClientResponse, any, any> } & { [K in number | symbol]: never }>(cases: Cases): <R>(self: With<E, R>) => With<Exclude<E, { _tag: keyof Cases; }> | { [K in string | number | symbol]: Cases[K] extends (...args: Array<any>) => Effect<any, E, any> ? E : never }[keyof Cases], R | { [K in string | number | symbol]: Cases[K] extends (...args: Array<any>) => Effect<any, any, R> ? R : never }[keyof Cases]>; <E extends { _tag: string; }, R, Cases extends { [K in string]: (error: Extract<E, { _tag: K; }>) => Effect<HttpClientResponse, any, any> } | { [K in string]: (error: Extract<E, { _tag: K; }>) => Effect<HttpClientResponse, any, any> } & { [K in number | symbol]: never }>(self: With<E, R>, cases: Cases): With<Exclude<E, { _tag: keyof Cases; }> | { [K in string | number | symbol]: Cases[K] extends (...args: Array<any>) => Effect<any, E, any> ? E : never }[keyof Cases], R | { [K in string | number | symbol]: Cases[K] extends (...args: Array<any>) => Effect<any, any, R> ? R : never }[keyof Cases]>;}Retries the request based on a provided schedule or policy.
Signature
declare const retry: { <E, O extends NoExcessProperties<Options<E>, O>>(options: O): <R>(self: With<E, R>) => With<O extends { schedule: Schedule.Schedule<infer _O, infer _I, infer _E, infer _R>; } ? _E | E : O extends { times: number; } ? E : O extends { until: Predicate.Refinement<E, infer E2>; } ? E2 : E | O extends { while: (...args: Array<any>) => Effect.Effect<infer _A, infer E, infer _R>; } ? E : never | O extends { until: (...args: Array<any>) => Effect.Effect<infer _A, infer E, infer _R>; } ? E : never, R | O extends { schedule: Schedule.Schedule<infer _O, infer _I, infer _E, infer R>; } ? R : never | O extends { while: (...args: Array<any>) => Effect.Effect<infer _A, infer _E, infer R>; } ? R : never | O extends { until: (...args: Array<any>) => Effect.Effect<infer _A, infer _E, infer R>; } ? R : never>; <B, E, ES, R1>(policy: Schedule<B, NoInfer<E>, ES, R1>): <R>(self: With<E, R>) => With<E | ES, R1 | R>; <E, R, O extends NoExcessProperties<Options<E>, O>>(self: With<E, R>, options: O): With<O extends { schedule: Schedule.Schedule<infer _O, infer _I, infer _E, infer _R>; } ? _E | E : O extends { times: number; } ? E : O extends { until: Predicate.Refinement<E, infer E2>; } ? E2 : E | O extends { while: (...args: Array<any>) => Effect.Effect<infer _A, infer E, infer _R>; } ? E : never | O extends { until: (...args: Array<any>) => Effect.Effect<infer _A, infer E, infer _R>; } ? E : never, R | O extends { schedule: Schedule.Schedule<infer _O, infer _I, infer _E, infer R>; } ? R : never | O extends { while: (...args: Array<any>) => Effect.Effect<infer _A, infer _E, infer R>; } ? R : never | O extends { until: (...args: Array<any>) => Effect.Effect<infer _A, infer _E, infer R>; } ? R : never>; <E, R, B, ES, R1>(self: With<E, R>, policy: Schedule<B, E, ES, R1>): With<E | ES, R | R1>;}retryTransient
unstableRetries common transient errors, such as rate limiting, timeouts or network issues.
When to use
Use to focus on retrying errors, transient responses, or both.
Details
Specifying a while predicate allows you to consider other errors as
transient, and is ignored in "response-only" mode.
A Retry-After header on a transient response, or on the response of a
status code error, sets the minimum delay before the next attempt.
Signature
declare const retryTransient: { <E, B = never, ES = never, R1 = never, RetryOn extends "response-only" | "errors-only" | "errors-and-responses" = "response-only" | "errors-only" | "errors-and-responses", Input = RetryOn extends "errors-only" ? E : RetryOn extends "response-only" ? HttpClientResponse : HttpClientResponse | E>(options: { readonly retryOn?: RetryOn; readonly schedule?: Schedule.Schedule<B, NoInfer<Input>, ES, R1>; readonly times?: number; readonly while?: Predicate.Predicate<NoInfer<E | ES>>; }): <R>(self: With<E, R>) => With<E | ES, R1 | R>; <E, R, B = never, ES = never, R1 = never, RetryOn extends "response-only" | "errors-only" | "errors-and-responses" = "response-only" | "errors-only" | "errors-and-responses", Input = RetryOn extends "errors-only" ? E : RetryOn extends "response-only" ? HttpClientResponse : HttpClientResponse | E>(self: With<E, R>, options: { readonly retryOn?: RetryOn; readonly schedule?: Schedule.Schedule<B, NoInfer<Input>, ES, R1>; readonly times?: number; readonly while?: Predicate.Predicate<NoInfer<E | ES>>; }): With<E | ES, R | R1>; <B, E, ES = never, R1 = never>(options: Schedule<B, NoInfer<HttpClientResponse | E>, ES, R1>): <R>(self: With<E, R>) => With<E | ES, R1 | R>; <E, R, B, ES = never, R1 = never>(self: With<E, R>, options: Schedule<B, NoInfer<HttpClientResponse | E>, ES, R1>): With<E | ES, R | R1>;}Fails requests that do not receive a response within the given duration.
When to use
Use to configure a timeout once on the client, for example when providing
the HttpClient service, while keeping the standard HttpClientError error
model.
Details
A timed out request is interrupted and fails with an HttpClientError whose
reason is a TransportError with a Cause.TimeoutError cause.
retryTransient treats it as transient. Interrupting a request aborts the
underlying transport, unless the request is attached to a scope with
withScope, in which case it stays open until the scope closes.
The timer starts after request preprocessing and covers everything the
wrapped client does to produce a response. For a plain client this ends when
the response headers arrive, but response middleware applied before
timeout, such as tap or retryTransient, runs inside the budget,
including any body reads it performs. Composition order therefore decides
how it interacts with retries: applying timeout before retryTransient
gives each attempt its own budget, while applying it after bounds the whole
retry loop.
Gotchas
Body reads outside the timed client are not covered, including those made
by response middleware applied after timeout and by consumers of the
HttpClient service. Apply a separate timeout to body reads such as
response.json or response.stream when needed.
Signature
declare const timeout: { (duration: Input): <E, R>(self: With<E, R>) => With<HttpClientError | E, R>; <E, R>(self: With<E, R>, duration: Input): With<HttpClientError | E, R>;}Example Timing out each attempt
import { Effect, Layer } from "effect"import { FetchHttpClient, HttpClient } from "effect/http"
const TimedHttpClient = Layer.effect( HttpClient.HttpClient, Effect.map( HttpClient.HttpClient, HttpClient.timeout("5 seconds") )).pipe(Layer.provide(FetchHttpClient.layer))
const program = Effect.gen(function*() { const client = (yield* HttpClient.HttpClient).pipe( HttpClient.retryTransient({ times: 3 }) ) return yield* client.get("https://example.com")}).pipe(Effect.provide(TimedHttpClient))Filtering
filterOrElse
unstableFilters the result of a response, or runs an alternative effect if the predicate fails.
Signature
declare const filterOrElse: { <B extends HttpClientResponse, E2, R2>(refinement: Refinement<HttpClientResponse, B>, orElse: (response: EqualsWith<HttpClientResponse, B, HttpClientResponse, Exclude<HttpClientResponse, B>>) => Effect<HttpClientResponse, E2, R2>): <E, R>(self: With<E, R>) => With<E2 | E, R2 | R>; <E2, R2>(predicate: Predicate<HttpClientResponse>, orElse: (response: HttpClientResponse) => Effect<HttpClientResponse, E2, R2>): <E, R>(self: With<E, R>) => With<E2 | E, R2 | R>; <E, R, B extends HttpClientResponse, E2, R2>(self: With<E, R>, refinement: Refinement<HttpClientResponse, B>, orElse: (response: EqualsWith<HttpClientResponse, B, HttpClientResponse, Exclude<HttpClientResponse, B>>) => Effect<HttpClientResponse, E2, R2>): With<E | E2, R | R2>; <E, R, E2, R2>(self: With<E, R>, predicate: Predicate<HttpClientResponse>, orElse: (response: HttpClientResponse) => Effect<HttpClientResponse, E2, R2>): With<E | E2, R | R2>;}filterOrFail
unstableFilters successful responses, or fails with the error produced by orFailWith when the predicate does not match.
Signature
declare const filterOrFail: { <B extends HttpClientResponse, E2>(refinement: Refinement<HttpClientResponse, B>, orFailWith: (response: HttpClientResponse) => E2): <E, R>(self: With<E, R>) => With<E2 | E, R>; <E2>(predicate: Predicate<HttpClientResponse>, orFailWith: (response: HttpClientResponse) => E2): <E, R>(self: With<E, R>) => With<E2 | E, R>; <E, R, B extends HttpClientResponse, E2>(self: With<E, R>, refinement: Refinement<HttpClientResponse, B>, orFailWith: (response: HttpClientResponse) => E2): With<E | E2, R>; <E, R, E2>(self: With<E, R>, predicate: Predicate<HttpClientResponse>, orFailWith: (response: HttpClientResponse) => E2): With<E | E2, R>;}filterStatus
unstableFilters responses by HTTP status code.
Signature
declare const filterStatus: { (f: (status: number) => boolean): <E, R>(self: With<E, R>) => With<HttpClientError | E, R>; <E, R>(self: With<E, R>, f: (status: number) => boolean): With<HttpClientError | E, R>;}filterStatusOk
unstableFilters responses that return a 2xx status code.
Signature
declare const filterStatusOk: <E, R>(self: HttpClient.With<E, R>) => HttpClient.With<E | Error.HttpClientError, R>Guards
isHttpClient
unstableReturns true if the provided value is an HttpClient.
Signature
declare function isHttpClient(u: unknown): u is HttpClientLayers
layerMergedContext
unstableCreates an HttpClient layer and merges the layer construction context into client response effects.
Signature
declare function layerMergedContext<E, R>(effect: Effect<HttpClient, E, R>): Layer<HttpClient, E, R>Mapping
mapRequest
unstableAppends a transformation of the request object before sending it.
Signature
declare const mapRequest: { (f: (a: HttpClientRequest) => HttpClientRequest): <E, R>(self: With<E, R>) => With<E, R>; <E, R>(self: With<E, R>, f: (a: HttpClientRequest) => HttpClientRequest): With<E, R>;}mapRequestEffect
unstableAppends an effectful transformation of the request object before sending it.
Signature
declare const mapRequestEffect: { <E2, R2>(f: (a: HttpClientRequest) => Effect<HttpClientRequest, E2, R2>): <E, R>(self: With<E, R>) => With<E2 | E, R2 | R>; <E, R, E2, R2>(self: With<E, R>, f: (a: HttpClientRequest) => Effect<HttpClientRequest, E2, R2>): With<E | E2, R | R2>;}mapRequestInput
unstablePrepends a transformation of the request object before sending it.
Signature
declare const mapRequestInput: { (f: (a: HttpClientRequest) => HttpClientRequest): <E, R>(self: With<E, R>) => With<E, R>; <E, R>(self: With<E, R>, f: (a: HttpClientRequest) => HttpClientRequest): With<E, R>;}mapRequestInputEffect
unstablePrepends an effectful transformation of the request object before sending it.
Signature
declare const mapRequestInputEffect: { <E2, R2>(f: (a: HttpClientRequest) => Effect<HttpClientRequest, E2, R2>): <E, R>(self: With<E, R>) => With<E2 | E, R2 | R>; <E, R, E2, R2>(self: With<E, R>, f: (a: HttpClientRequest) => Effect<HttpClientRequest, E2, R2>): With<E | E2, R | R2>;}Transforms a client by wrapping the response effect for each request.
Details
The transformation receives both the response effect and the original request, allowing it to change success, error, and environment behavior.
Signature
declare const transform: { <E, R, E1, R1>(f: (effect: Effect<HttpClientResponse, E, R>, request: HttpClientRequest) => Effect<HttpClientResponse, E1, R1>): (self: With<E, R>) => With<E | E1, R | R1>; <E, R, E1, R1>(self: With<E, R>, f: (effect: Effect<HttpClientResponse, E, R>, request: HttpClientRequest) => Effect<HttpClientResponse, E1, R1>): With<E | E1, R | R1>;}transformResponse
unstableTransforms a client by applying an effectful transformation to each response effect.
Signature
declare const transformResponse: { <E, R, E1, R1>(f: (effect: Effect<HttpClientResponse, E, R>) => Effect<HttpClientResponse, E1, R1>): (self: With<E, R>) => With<E1, R1>; <E, R, E1, R1>(self: With<E, R>, f: (effect: Effect<HttpClientResponse, E, R>) => Effect<HttpClientResponse, E1, R1>): With<E1, R1>;}Models
HTTP client whose requests produce HttpClientResponse values and can fail with HttpClientError.
Signature
interface HttpClient extends With<Error.HttpClientError> {}Other
Signature
declare const catch: { <E, E2, R2>(f: (e: E) => Effect<HttpClientResponse, E2, R2>): <R>(self: With<E, R>) => With<E2, R2 | R>; <E, R, E2, R2>(self: With<E, R>, f: (e: E) => Effect<HttpClientResponse, E2, R2>): With<E2, R | R2>;}HttpClient
unstableNamespace containing type-level members associated with HttpClient.
Namespace containing type-level helpers for retrying HTTP clients.
Namespace containing configuration types for withCircuitBreaker.
WithRateLimiter
unstableNamespace containing configuration types for withRateLimiter.
Predicates
isTransientError
unstableReturns true for an error that retryTransient retries by default: a
timeout, a transport error, or a status code error with a transient response.
When to use
Use to classify failures the same way retryTransient does, for example in a
custom retry policy or a circuit breaker.
See
- isTransientResponse for the response statuses it accepts
- retryTransient for the retry policy that uses it
Signature
declare function isTransientError(error: unknown): booleanExample Classifying client errors
import { Cause } from "effect"import { HttpClient, HttpClientError, HttpClientRequest } from "effect/http"
const request = HttpClientRequest.get("https://example.com")const transportError = new HttpClientError.HttpClientError({ reason: new HttpClientError.TransportError({ request })})
HttpClient.isTransientError(transportError) // => trueHttpClient.isTransientError(new Cause.TimeoutError()) // => trueHttpClient.isTransientError(new Error("boom")) // => falseisTransientResponse
unstableReturns true for a response whose status retryTransient retries by
default: 408, 429, 500, 502, 503 or 504.
When to use
Use to retry the same responses as retryTransient in a custom retry policy.
See
- isTransientError for the matching error predicate
- retryTransient for the retry policy that uses it
Signature
declare function isTransientResponse(response: HttpClientResponse): booleanRate Limiting
withRateLimiter
unstableApplies request rate limiting using the RateLimiter service.
Details
It can update limits by inspecting common rate limit response headers and
automatically retries HTTP 429 responses (or HttpClientError values
wrapping a 429 response) by forcing the retry back through the limiter.
When a response reports the remaining budget, requests wait for the
reported reset once that budget is exhausted.
Gotchas
Automatic HTTP 429 retries are unlimited unless times is specified.
Disabling response inspection does not disable retries; set times to 0
to return or fail with the first 429.
Signature
declare const withRateLimiter: { (options: Options): <E, R>(self: With<E, R>) => With<E | RateLimiterError, R>; <E, R>(self: With<E, R>, options: Options): With<E | RateLimiterError, R>;}Redirects
followRedirects
unstableEnables following HTTP redirects up to a specified number of times.
Details
Follows 3xx responses that include a Location header, up to
maxRedirects (default 10) times. When the limit is reached or the
Location header is not a valid URL, the last redirect response is returned.
Gotchas
This only sees redirects that the underlying client returns. fetch
follows redirects itself by default, so with FetchHttpClient provide
FetchHttpClient.RequestInit with { redirect: "manual" }. Browsers return
an opaque response without a Location header for manual redirects, so
this cannot follow them there.
Signature
declare const followRedirects: { (maxRedirects?: number): <E, R>(self: With<E, R>) => With<E, R>; <E, R>(self: With<E, R>, maxRedirects?: number): With<E, R>;}Example Following redirects with FetchHttpClient
import { Effect } from "effect"import { FetchHttpClient, HttpClient } from "effect/http"
const program = Effect.gen(function*() { const client = (yield* HttpClient.HttpClient).pipe( HttpClient.followRedirects(5) ) return yield* client.get("https://example.com/redirect")}).pipe( Effect.provide(FetchHttpClient.layer), Effect.provideService(FetchHttpClient.RequestInit, { redirect: "manual" }))Resource Management
Sequencing
Performs an additional effect after a successful request.
Signature
declare const tap: { <_, E2, R2>(f: (response: HttpClientResponse) => Effect<_, E2, R2>): <E, R>(self: With<E, R>) => With<E2 | E, R2 | R>; <E, R, _, E2, R2>(self: With<E, R>, f: (response: HttpClientResponse) => Effect<_, E2, R2>): With<E | E2, R | R2>;}Performs an additional effect after an unsuccessful request.
Signature
declare const tapError: { <_, E, E2, R2>(f: (e: NoInfer<E>) => Effect<_, E2, R2>): <R>(self: With<E, R>) => With<E | E2, R2 | R>; <E, R, _, E2, R2>(self: With<E, R>, f: (e: NoInfer<E>) => Effect<_, E2, R2>): With<E | E2, R | R2>;}tapRequest
unstablePerforms an additional effect on the request before sending it.
Signature
declare const tapRequest: { <_, E2, R2>(f: (a: HttpClientRequest) => Effect<_, E2, R2>): <E, R>(self: With<E, R>) => With<E2 | E, R2 | R>; <E, R, _, E2, R2>(self: With<E, R>, f: (a: HttpClientRequest) => Effect<_, E2, R2>): With<E | E2, R | R2>;}Services
HttpClient
unstableService tag for the default outgoing HTTP client service.
When to use
Use to provide the default outgoing HTTP client service used by request
accessors such as execute, get, and post.
Signature
declare const HttpClient: Service<HttpClient, HttpClient>SpanNameGenerator
unstableContext reference for generating the span name used for outgoing client request spans.
Details
Defaults to the request method unchanged.
Signature
declare const SpanNameGenerator: Reference<(request: HttpClientRequest) => string>TracerDisabledWhen
unstableContext reference for a predicate that disables client-side tracing for matching outgoing requests.
Signature
declare const TracerDisabledWhen: Reference<Predicate<HttpClientRequest>>TracerHeaderFilter
unstableContext reference for filtering request and response headers added to client spans.
Details
Header capture is opt-in: the default filter records no headers. Captured
headers listed in Headers.CurrentRedactedNames are recorded as <redacted>.
Signature
declare const TracerHeaderFilter: Reference<(headerName: string, phase: "request" | "response") => boolean>TracerPropagationEnabled
unstableContext reference that controls whether outgoing client spans are propagated to request headers.
Details
When this is true, the client writes the compact B3 b3 header and the
W3C traceparent header. The default is on. The client span is still
created when this is false.
Gotchas
A browser preflight fails when the target does not list b3 and
traceparent in Access-Control-Allow-Headers. Set this to false for
those requests.
Signature
declare const TracerPropagationEnabled: Reference<boolean>