How to intercept JavaScript Fetch API requests and responses
JavaScript

How to intercept JavaScript Fetch API requests and responses

When working with JavaScript Fetch API, you may want to intercept requests and responses to add custom headers, modify the request or response, or log the request and response data. In this article, you will learn how to intercept Fetch API requests and responses using the Fetch API interceptors.

Before we dive into the code, let's first understand what the Fetch API is and how it works. fetch API is a modern interface for fetching resources (like JSON, images, and other files) across the network. It is built into the global window object, which means you can access it from anywhere in your JavaScript code. Fetch api is promise based, which means you can use the then and catch methods to handle the response data and errors. Fetch API is supported in all modern browsers, including Chrome, Firefox, Safari, and Edge. Now that you have a basic understanding of the Fetch API, let's see how you can intercept requests and responses using the Fetch API interceptors.
The syntax:
const responsePromise = fetch(resource [, init]);
first parameter defines the resource you want to fetch, which can be either a Request object or a URL. init is an optional parameter that will contain any configuration you want to apply to the request. By default, Fetch uses the GET method for API calls.
Here is an example of how you can use the Fetch API to make a GET request to a URL and log the response data to the console:
fetch("https://api.example.com/data").then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));

Implementing interceptors:

You can also use any third party package to to implement this but here we are going to write our own code :
Let’s take a step-by-step look at how you can create an interceptor for the Fetch API.
const { fetch: originalFetch } = window;
window.fetch = async (...args) => {
    const [resource, config ] = args;
    // request interceptor here
    const response = await originalFetch(resource, config);
    // response interceptor here
    return response;
};
The code above overrides the original fetch with a custom implementation and calls the original fetch method inside it.

Request interceptor:

Let's create a request interceptor, In the example below, a simple request interceptor that changes the resource URL :
const { fetch: originalFetch } = window;
window.fetch = async (...args) => {
    let [resource, config ] = args;
    // request interceptor starts
    resource = 'https://dummyjson.com/posts';
    // request interceptor ends
    const response = await originalFetch(resource, config);
    // response interceptor here
    return response;
};

fetch('https://dummyjson.com/posts/search?q=love')
.then((response) => response.json())
.then((json) => console.log(json));
The fetch request now will fetch data from https://dummyjson.com/posts instead of https://dummyjson.com/posts/search?q=love.

Response interceptor:

Let now implement a response interceptor, The response interceptor would intercept the API response before it is accessed. Let’s take a look at the following code:
const { fetch: originalFetch } = window;
window.fetch = async (...args) => {
  let [resource, config] = args;
  let response = await originalFetch(resource, config);
  // response interceptor
  const json = () =>
    response
      .clone()
      .json()
      .then((data) => ({ ...data, customField: `Intercepted: ${data.title}` }));

  response.json = json;
  return response;
};
fetch('https://dummyjson.com/posts/1')
  .then((response) => response.json())
  .then((json) => console.log(json));
Above code, changed the JSON method to return some custom data instead of the original data.

Handling errors:

you can also handle errors in the fetch interceptor by checking the response status code and rejecting the promise if the response status code is not in the 200 range. Here is an example of how to handle 404 errors in the fetch interceptor.
const { fetch: originalFetch } = window;
window.fetch = async (...args) => {
  let [resource, config] = args;
  let response = await originalFetch(resource, config);
  if (?response.ok && response.status === 404) {
    // 404 error handling
    return Promise.reject(response);
  }
  return response;
};
fetch('https://dummyjson.com/posts/dfdff')
  .then((response) => response.json())
  .then((json) => console.log(json))
  .catch((error) => console.error(error));
Cool, you have a Fetch API request and response interceptor. You can now intercept requests and responses to add custom headers, modify the request or response, or log the request and response data. This is useful when you want to add authentication headers, modify the request or response data, or log the request and response data for debugging purposes. You can also use the Fetch API interceptors to implement caching, retry logic, or other custom logic. The Fetch API interceptors are a powerful feature that allows you to customize the behavior of the Fetch API to meet your specific requirements. I hope you found this article helpful. Please follow me on Twitter and GitHub for more articles and tutorials. Thank you for reading?