Skip to content

Interceptor pipeline

Interceptors mutate a shared FetchExchange; they return void | Promise<void>, not a replacement exchange. RequestInterceptor, ResponseInterceptor, and ErrorInterceptor are structural specializations of Interceptor, whose required fields are name, order, and intercept(exchange).

Registration and ordering

new InterceptorRegistry(interceptors = []) sorts ascending by order. use(interceptor): boolean rejects a duplicate name; eject(name): boolean reports whether removal happened; clear(): void removes everything. The constructor sorts a copy of the provided array and leaves the input array unchanged; it does not de-duplicate its initial entries. interceptors returns an array copy. intercept(exchange): Promise<void> awaits handlers sequentially and stops on rejection. The registry itself implements Interceptor, with constructor-name name and order Number.MIN_SAFE_INTEGER.

OrderedCapable.order is optional; sortOrder(a, b) treats missing values as zero. toSorted(array, filter?) returns a sorted copy, optionally filtered. DEFAULT_INTERCEPTOR_ORDER_STEP = 1000 and BUILT_IN_INTERCEPTOR_ORDER_STEP = 10000 provide spacing.

Built-in phases

Registry / implementationExported orderEffect
request: RequestBodyInterceptorREQUEST_BODY_INTERCEPTOR_ORDER = MIN_SAFE_INTEGER + 10000Normalize body and Content-Type.
request: UrlResolveInterceptorURL_RESOLVE_INTERCEPTOR_ORDER = MAX_SAFE_INTEGER - 20000Resolve base/path/query, clear urlParams.
request: FetchInterceptorFETCH_INTERCEPTOR_ORDER = MAX_SAFE_INTEGER - 10000Await timeoutFetch, assign response.
response: ValidateStatusInterceptorVALIDATE_STATUS_INTERCEPTOR_ORDER = MAX_SAFE_INTEGER - 10000Reject unaccepted status unless bypassed.

Each corresponding *_INTERCEPTOR_NAME equals the implementation's class name. A request interceptor with order zero sees a normalized body but an unresolved URL. A response interceptor with order zero runs before default status validation. Removing FetchInterceptor means no built-in HTTP I/O; clear() is not merely removing custom hooks.

Failure and recovery

new InterceptorManager(validateStatus?) constructs these request/response registries and an empty error registry. exchange(exchange) runs request then response. On rejection it stores the thrown value in exchange.error, runs the error registry, then throws an ExchangeError if hasError() remains true.

An error interceptor recovers by supplying any needed response/result state and clearing exchange.error. The response chain is not rerun after recovery, so recovered responses must already meet the application's policy. A throw from the error chain escapes directly and prevents later error interceptors. Error interceptors are not automatic retries, and extractor failures occur outside this manager.

Interceptors added to a shared client remain until ejected. Use distinct stable names and remove request-specific instrumentation when its owner ends; do not accumulate a new interceptor per request.

Complete example

ts
import { Fetcher, setHeader } from '@ahoo-wang/fetcher';

const client = new Fetcher({ baseURL: 'https://api.example.com' });
client.interceptors.request.use({
  name: 'trace',
  order: 0,
  intercept(exchange) {
    setHeader(exchange.ensureRequestHeaders(), 'X-Trace-Id', 'demo-trace');
  },
});
console.assert(client.interceptors.request.eject('trace'));

Public symbols and source

SymbolImplementation
FETCH_INTERCEPTOR_NAMEfetchInterceptor.ts:24
FETCH_INTERCEPTOR_ORDERfetchInterceptor.ts:30
FetchInterceptorfetchInterceptor.ts:54
DEFAULT_INTERCEPTOR_ORDER_STEPinterceptor.ts:18
BUILT_IN_INTERCEPTOR_ORDER_STEPinterceptor.ts:20
Interceptorinterceptor.ts:44
RequestInterceptorinterceptor.ts:111
ResponseInterceptorinterceptor.ts:135
ErrorInterceptorinterceptor.ts:164
InterceptorRegistryinterceptor.ts:189
InterceptorManagerinterceptorManager.ts:48
OrderedCapableorderedCapable.ts:29
sortOrderorderedCapable.ts:53
toSortedorderedCapable.ts:87
REQUEST_BODY_INTERCEPTOR_NAMErequestBodyInterceptor.ts:25
REQUEST_BODY_INTERCEPTOR_ORDERrequestBodyInterceptor.ts:30
RequestBodyInterceptorrequestBodyInterceptor.ts:50
URL_RESOLVE_INTERCEPTOR_NAMEurlResolveInterceptor.ts:24
URL_RESOLVE_INTERCEPTOR_ORDERurlResolveInterceptor.ts:29
UrlResolveInterceptorurlResolveInterceptor.ts:53

Package index

Released under the Apache License 2.0.