nuxt-community / axios-module

Secure and easy axios integration for Nuxt 2
https://axios.nuxtjs.org
MIT License
1.2k stars 246 forks source link

When server-side rendering, remove unserializable attributes from Axios error #422

Open thomasboyt opened 3 years ago

thomasboyt commented 3 years ago

I've encountered an issue where, when I have an unhandled Axios error in my Nuxt fetch() hook, I wind up with an odd "Maximum call stack size exceeded" exceeded error.

This error happens because Axios's default error objects contain circular references that cannot be serialized to JSON. The fetch hook (as well as the context.error() API used for full-page errors) serializes the error to JSON so that it can be accessed in client logic.

I've found a lot of people don't seem to understand that this error indicates an underlying Axios response error, leading to a lot of confused and frustrated posts from folks who have no idea why they're suddenly seeing this error:

There's a simple, if opinionated solution to this: we can just ensure that any Axios errors from server-rendering only contain the subset of an Axios error that can be serialized. A simple proof of concept interceptor plugin I've used to fix my app is the following:

export default function ({ $axios, store }) {
  // Prevent unhandled Axios errors in SSR from throwing an error when
  // serialized
  $axios.onError((error) => {
    // only need to fix during SSR
    if (process.server) {
      // request errors do not seem to have this issue
      if (error.response) {
        // construct a new error object in the same form as the Axios error.
        // this is a simplified subset of the Axios error object that I need
        // for my app, but if this was implemented in this library, it would
        // contain the rest of err.response that can be serialized (e.g.
        // headers, statusText, etc.)
        const err = new Error(
          `Request failed with status code ${error.response.status}`
        );
        err.response = {
          data: error.response.data,
          status: error.response.status,
        };
        err.isAxiosError = true;
        return Promise.reject(err);
      }
    }
  });
}

If this seems like a good idea to be included in the library, I would be happy to contribute a pull request.

simllll commented 3 years ago

I ended up with following error object:

const config = error.response?.config || error.config;

err.response = {
    data: error.response.data,
    status: error.response.status,
    statusText: error.response.statusText,
    headers: error.response.headers,
    config: config && {
        url: config.url,
        method: config.method,
        headers: config.headers,
        params: config.params
    }
};
albanm commented 3 years ago

This one should really receive attention, it is very frustrating ! @nuxt/axios is just not compatible with the fetch hook.

Also the serialization util should really provide a little bit of help here by giving some context to the serialization error like the object key, the originating component, etc.

farnabaz commented 3 years ago

Hey, ~Do you mind create a reproduction sample by forking template.nuxtjs.org~

A reproduction sample is provided in #360. https://codesandbox.io/s/eloquent-mountain-uh6f8?file=/plugins/axios.js

zhanglong12138 commented 3 years ago

The problem will not appear but exist