Interceptors

Add middleware to the request/response pipeline. Auth, logging, transforms — all async-aware.

Request Interceptors

Run before fetch. Each receives the config and must return it (modified or not).

// Add auth header to every request
api.interceptors.request.use((config) => ({
  ...config,
  headers: {
    ...config.headers,
    Authorization: `Bearer ${getToken()}`,
  },
}))

Response Interceptors

Run after fetch and parsing. Each receives the response and must return it.

// Unwrap nested API responses
api.interceptors.response.use((response) => ({
  ...response,
  data: response.data.result,
}))

Async Interceptors

Interceptors can be async functions — they are awaited automatically in sequence.

// Async interceptors are awaited automatically
api.interceptors.request.use(async (config) => {
  const token = await refreshTokenIfNeeded()
  return {
    ...config,
    headers: { ...config.headers, Authorization: `Bearer ${token}` },
  }
})

Error Handlers

use() accepts an optional second argument — an error handler that catches if the interceptor throws.

// Second argument is an error handler
api.interceptors.request.use(
  (config) => {
    throw new Error("something went wrong")
  },
  (error) => {
    console.error("Interceptor failed:", error)
    // Error is caught — request continues without this interceptor's changes
  }
)

Ejecting

Remove a registered interceptor by its ID.

// Register returns an ID
const id = api.interceptors.request.use(myInterceptor)

// Remove by ID
api.interceptors.request.eject(id)

Execution Order

Multiple interceptors run in registration order. Each passes its result to the next.

// Interceptors run in registration order (FIFO)
api.interceptors.request.use(first)   // runs 1st
api.interceptors.request.use(second)  // runs 2nd
api.interceptors.request.use(third)   // runs 3rd

// Each receives the output of the previous one

Example: Logging

// Logging interceptor
api.interceptors.response.use((response) => {
  console.log(`[${response.status}] ${response.config.method} ${response.config.url}`)
  return response
})