I'm trying to create a "retry" functionality for a request containing a FormData
as data.
The retry happen when the JWT token is expired, my second request (the retry one) doesn't contain any data.
The idea:
const axiosInstance = axios.create();
/**
* Before each request, we'll add a possible retry if the
* request need a refreshed token
*/
axiosInstance.interceptors.request.use((request) => {
if (typeof _.get(request, ['retried']) === 'undefined') {
request.retried = false;
}
return request;
});
/**
* After a request with an error, we'll check if the error is a token not refreshed.
* If we didn't already tried to refresh, we'll just fallback to the errorHandler function
*/
axiosInstance.interceptors.response.use(null, async (error) => {
const statusCode = _.get(error, ['response', 'data', 'statusCode']);
const message = _.get(error, ['response', 'data', 'message']);
const { config: request = {} } = error;
if (statusCode === 401 && !request.retried) {
try {
const newTokens = await refreshTokens();
request.retried = true;
_.set(request, ['headers', 'authorization'], newTokens.accessToken);
return axiosInstance.request(request);
} catch (e) {
return error;
}
}
return error;
});
The request:
const formData = new FormData();
formData.append('name', name);
formData.append('file', fs.createReadStream(file.path));
axiosInstance.post(
'http://localhost/upload',
formData,
{
headers: {
...formData.getHeaders(),
authorization: tokens.accessToken
}
}
);
If my token expired, the request will fail, the interceptor will then refresh my tokens, and retry the exact same request with just the new header Authorization
. Yet, on the server side, the received payload is always null.
As far as I know, the formData needs to be added again on the retry (I think it is due to the data being added as a stream and consumed during the request, so a new retry cannot consume the already consumed stream).
You can take a look at request.data
to see what I mean.