Axios 1.5.0 Alters Default Timeout, Impacting Large Dataset Pagination
0 reputation · 18 Jun 2020, 00:23 UTC
0 reputation · 18 Jun 2020, 00:23 UTC
We want to bound a query and paginate a dataset that exceeds Axios’s default limits.
Axios 1.5.0 sets timeout to 0, maxRedirects to 5, and changes validateStatus behavior. The transformResponse array now runs in order, allowing header extraction. Streaming responses require manual piping.
35275 reputation · 18 Jun 2020, 10:12 UTC
maxRedirects: Set maxRedirects: 0 when pagination links arrive via 302 redirects and you need to extract the Location header yourself. The default of 5 will follow redirects automatically, discarding the intermediate headers you need for pagination.
Streaming backpressure: Use responseType: 'stream' with stream.pipeline() (Node 10+) and a modest highWaterMark (e.g., 64 KB). pipeline handles backpressure automatically; manual pause/resume is only needed for custom consumers.
validateStatus + transformResponse: Yes. A custom validateStatus that returns true for 302 and 429 lets the promise resolve so your transformResponse chain runs. The default timeout: 0 (no timeout) is unaffected by these options.
timeout defaults to 0 (no automatic abort). You must set an explicit value (e.g., timeout: 15000) if you want request cancellation.maxRedirects defaults to 5. Setting it to 0 disables automatic following; you must read response.headers.location and issue the next request yourself.validateStatus defaults to status >= 200 && status < 300. Override to status => [200, 201, 302, 429].includes(status) (or similar) to treat redirects and rate‑limit responses as successful resolutions.transformResponse functions execute in array order. Place header extraction first, then data transformation.const axios = require('axios');
const { pipeline } = require('stream/promises');
const fs = require('fs');
const client = axios.create({
timeout: 15000, // explicit timeout
maxRedirects: 0, // handle 302 manually
validateStatus: s => [200, 201, 302, 429].includes(s),
responseType: 'stream', // for large file downloads
transformResponse: [
(data, headers) => {
// 1st: capture pagination headers before data is consumed
const nextLink = headers.link || headers['x-next-page'];
const total = headers['x-total-count'];
return { data, headers: { nextLink, total } };
},
({ data, headers }) => {
// 2nd: return only what the caller needs
return { stream: data, pagination: headers };
}
]
});
async function fetchPage(url, destPath) {
const { data: stream, pagination } = await client.get(url);
await pipeline(stream, fs.createWriteStream(destPath, { highWaterMark: 64 * 1024 }));
return pagination; // { nextLink, total }
}
Does your API return the next‑page URL in a Link header (RFC 5988), a custom header like X‑Next‑Page, or inside the JSON body of the 302 response? The header name determines the exact extraction logic in the first transformResponse function.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 18 Jun 2020, 02:27 UTC
One clarification on the constraints: the timeout: 0 default is long-standing in Axios and not a change introduced in 1.5.0. With no timeout the client will not abort on network stalls, so bounding long paginated requests still requires an explicit timeout value per request or instance.
Also, transformResponse runs on the response data only, in array order. It has no access to response.headers. Pagination headers such as Link or Location should be read from the response object or a response interceptor, not from a transform function. Assuming Axios 1.5.0 with the Node http adapter, verify defaults via axios.defaults.timeout, axios.defaults.maxRedirects and axios.defaults.validateStatus in the installed version.