Skip to content

Interceptors

14.2.1. Request Interceptors

  • Request interceptors are executed before all API requests are sent to the server.
  • The authentication token must be automatically injected into the Authorization header within the request interceptor.
  • Token injection logic must be separated and managed in src/api/interceptors/auth.ts.
typescript
// src/api/interceptors/auth.ts
import type { InternalAxiosRequestConfig } from 'axios'
import { useAuthStore } from '@/stores/useAuthStore'

export function attachAuthToken(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
  const authStore = useAuthStore()
  const token = authStore.accessToken

  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }

  return config
}

14.2.2. Response Interceptors

  • Response interceptors are executed before the server response is delivered to the component.
  • Error responses must be transformed into a standardized format within the interceptor.
typescript
// src/api/interceptors/error.ts
import type { AxiosError } from 'axios'
import type { ApiError } from '@/types/api'

export function handleResponseError(error: AxiosError<ApiError>): Promise<never> {
  if (!error.response) {
    return Promise.reject({
      status: 0,
      message: 'Please check your network connection.',
      code: 'NETWORK_ERROR',
    })
  }

  const { status, data } = error.response

  return Promise.reject({
    status,
    message: data?.message ?? 'An unknown error occurred.',
    code: data?.code ?? 'UNKNOWN_ERROR',
  })
}

14.2.3. Logging Interceptors

  • In development environments, request and response information must be logged to the console.
  • In production environments, the logging interceptor must not be registered.
typescript
// src/api/interceptors/logger.ts
import type { InternalAxiosRequestConfig, AxiosResponse } from 'axios'

export function logRequest(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
  config.metadata = { startTime: Date.now() }
  console.log(`[API Request] ${config.method?.toUpperCase()} ${config.url}`)
  return config
}

export function logResponse(response: AxiosResponse): AxiosResponse {
  const duration = Date.now() - (response.config.metadata?.startTime ?? 0)
  console.log(`[API Response] ${response.config.url} → ${response.status} (${duration}ms)`)
  return response
}
  • The config.metadata type must be declared by adding a metadata?: { startTime: number } property to InternalAxiosRequestConfig via module augmentation (declare module 'axios').
  • Conditional registration must use import.meta.env.DEV.

14.2.4. Interceptor Registration Order

  • Request interceptors execute in LIFO (Last In, First Out) order. Response interceptors execute in FIFO (First In, First Out) order. Since the order affects logic execution, interceptors must be registered in the intended sequence.
CategoryExecution OrderRecommended Registration Order
Request interceptorsLIFO (Last In, First Out)Logging -> Auth token injection
Response interceptorsFIFO (First In, First Out)Error transformation -> Logging
typescript
// src/api/client.ts (final registration order)
if (import.meta.env.DEV) {
  apiClient.interceptors.request.use(logRequest)
}
apiClient.interceptors.request.use(attachAuthToken)

apiClient.interceptors.response.use((res) => res, handleResponseError)
if (import.meta.env.DEV) {
  apiClient.interceptors.response.use(logResponse)
}
  • Interceptor files must be separated by functionality under the src/api/interceptors/ directory.
  • Interceptor registration must be performed in a single location: src/api/client.ts. Interceptors must not be registered across multiple files.

TIENIPIA QUALIFIED STANDARD