Skip to main content

Extending Functionality with Interceptors

In this tutorial, you will learn how to use the built-in interceptor system to globally modify outgoing requests and incoming responses. This is useful for tasks like adding custom headers, logging API traffic, or handling specific response codes across your entire application.

Prerequisites

  • Access to the frontend directory of the project.
  • Familiarity with the OpenAPI configuration object located in frontend/src/client/core/OpenAPI.ts.

Step 1: Access the Global OpenAPI Object

The generated client uses a singleton OpenAPI object to manage its configuration. To add interceptors, you must import this object.

import { OpenAPI } from './client/core/OpenAPI';

The OpenAPI object contains an interceptors property with two specialized Interceptors instances: request and response.

Step 2: Implement a Request Interceptor

Request interceptors allow you to modify the AxiosRequestConfig before the request is sent. This is ideal for injecting dynamic headers or tracking request metadata.

Create a function that matches the Middleware<AxiosRequestConfig> type and register it using OpenAPI.interceptors.request.use().

import { OpenAPI } from './client/core/OpenAPI';
import type { AxiosRequestConfig } from 'axios';

// 1. Define the interceptor function
const logRequestInterceptor = (config: AxiosRequestConfig): AxiosRequestConfig => {
console.log(`[API Request] ${config.method?.toUpperCase()} ${config.url}`);

// You can modify headers here
if (config.headers) {
config.headers['X-Client-Timestamp'] = new Date().toISOString();
}

return config; // Always return the config
};

// 2. Register the interceptor
OpenAPI.interceptors.request.use(logRequestInterceptor);

As seen in frontend/src/client/core/request.ts, these functions are executed sequentially in the sendRequest function:

// Internal implementation in request.ts
for (const fn of config.interceptors.request._fns) {
requestConfig = await fn(requestConfig);
}

Step 3: Implement a Response Interceptor

Response interceptors allow you to inspect or transform the AxiosResponse before it is processed by the service methods. This is useful for global error handling or data normalization.

import { OpenAPI } from './client/core/OpenAPI';
import type { AxiosResponse } from 'axios';

// 1. Define the interceptor function
const responseTimeInterceptor = (response: AxiosResponse): AxiosResponse => {
const requestUrl = response.config.url;
console.log(`[API Response] Received from ${requestUrl} with status ${response.status}`);

return response; // Always return the response
};

// 2. Register the interceptor
OpenAPI.interceptors.response.use(responseTimeInterceptor);

Step 4: Remove an Interceptor

If you need to remove an interceptor (for example, when a component unmounts or a user logs out), use the eject method. This requires you to have a reference to the original function.

// To remove the interceptor later:
OpenAPI.interceptors.request.eject(logRequestInterceptor);

The eject method in frontend/src/client/core/OpenAPI.ts performs a reference check to find and remove the specific function from the internal _fns array.

Complete Example: Global Auth Header

While the template provides a TOKEN field in OpenAPIConfig, you might want to use an interceptor for more complex logic, such as adding a custom organization ID header from a local storage value:

import { OpenAPI } from './client/core/OpenAPI';

const orgHeaderInterceptor = (config: any) => {
const orgId = localStorage.getItem('org_id');
if (orgId && config.headers) {
config.headers['X-Org-ID'] = orgId;
}
return config;
};

// Apply globally
OpenAPI.interceptors.request.use(orgHeaderInterceptor);

Important Considerations

  • Return Value: Every middleware function must return the config or response object (or a Promise resolving to it). Failing to do so will cause the request chain to break.
  • Execution Order: Interceptors are executed in the order they are added.
  • Async Support: Interceptors can be async functions. The request logic in request.ts uses await when iterating through the interceptor functions.
  • Error Handling: If an interceptor throws an error, the request will fail and the error will be caught by the standard ApiError handling logic.