axios-retry
Advanced tools
+16
-2
@@ -8,8 +8,18 @@ # Change Log | ||
| ## [3.0.1] - 2017-08-16 | ||
| ### Fixed | ||
| - Fixed first request time not being taken into account in timeout across retries. | ||
| - Fixed negative timeouts being passed to XHR (browsers), causing that no timeout was applied. | ||
| - Fixed safe methods and idempotent errors not being retried on unknown network errors. | ||
| ## [3.0.0] - 2017-08-13 | ||
| ### Changed | ||
| - Retried errors on idempotent requests (5xx with get, head, options, put and delete) by default, | ||
| along with network errors. | ||
| along with safe network errors. | ||
| - Moved some hard-coded conditions to the default `retryCondition` function so users can define a | ||
| custom function that overwrites them. The conditions that verify that the error is not a timeout or an unsafe network error have been moved to `isNetworkError`. | ||
| custom function that overwrites them. The conditions that verify that the error is not a timeout or | ||
| an unsafe network error have been moved to `isNetworkError`. | ||
| ### Added | ||
@@ -19,2 +29,3 @@ - Added additional pre-defined retry conditions: `isSafeRequestError`, `isIdempotentRequestError`. | ||
| ## [2.0.1] - 2017-06-19 | ||
| ### Fixed | ||
@@ -24,2 +35,3 @@ - Removed dependency from the `package.json` file. | ||
| ## [2.0.0] - 2017-06-15 | ||
| ### Changed | ||
@@ -29,2 +41,3 @@ - Now the configured timeout in Axios is not for each retry request but for the whole request lifecycle. | ||
| ## [1.3.1] - 2017-06-19 | ||
| ### Fixed | ||
@@ -34,3 +47,4 @@ - Removed dependency from the `package.json` file. | ||
| ## [1.3.0] - 2017-06-15 | ||
| ### Added | ||
| - Allowed per-request configuration using the `axios-retry` namespace. |
+24
-9
@@ -23,9 +23,18 @@ import isRetryAllowed from 'is-retry-allowed'; | ||
| */ | ||
| function isRetryableError(error) { | ||
| return error.code !== 'ECONNABORTED' | ||
| && (!error.response || (error.response.status >= 500 && error.response.status <= 599)); | ||
| } | ||
| /** | ||
| * @param {Error} error | ||
| * @return {boolean} | ||
| */ | ||
| export function isSafeRequestError(error) { | ||
| if (!error.response || !error.config) { | ||
| if (!error.config) { | ||
| // Cannot determine if the request can be retried | ||
| return false; | ||
| } | ||
| return error.response.status >= 500 && error.response.status <= 599 | ||
| && SAFE_HTTP_METHODS.indexOf(error.config.method) !== -1; | ||
| return isRetryableError(error) && SAFE_HTTP_METHODS.indexOf(error.config.method) !== -1; | ||
| } | ||
@@ -38,8 +47,8 @@ | ||
| export function isIdempotentRequestError(error) { | ||
| if (!error.response || !error.config) { | ||
| if (!error.config) { | ||
| // Cannot determine if the request can be retried | ||
| return false; | ||
| } | ||
| return error.response.status >= 500 && error.response.status <= 599 | ||
| && IDEMPOTENT_HTTP_METHODS.indexOf(error.config.method) !== -1; | ||
| return isRetryableError(error) && IDEMPOTENT_HTTP_METHODS.indexOf(error.config.method) !== -1; | ||
| } | ||
@@ -134,2 +143,8 @@ | ||
| export default function axiosRetry(axios, defaultOptions) { | ||
| axios.interceptors.request.use((config) => { | ||
| const currentState = getCurrentState(config); | ||
| currentState.lastRequestTime = Date.now(); | ||
| return config; | ||
| }); | ||
| axios.interceptors.response.use(null, error => { | ||
@@ -160,7 +175,7 @@ const config = error.config; | ||
| const now = Date.now(); | ||
| if (config.timeout && currentState.lastRequestTime) { | ||
| config.timeout -= now - currentState.lastRequestTime; | ||
| const lastRequestDuration = Date.now() - currentState.lastRequestTime; | ||
| // Minimum 1ms timeout (passing 0 or less to XHR means no timeout) | ||
| config.timeout = Math.max(config.timeout - lastRequestDuration, 1); | ||
| } | ||
| currentState.lastRequestTime = now; | ||
@@ -167,0 +182,0 @@ return axios(config); |
+23
-7
@@ -37,8 +37,17 @@ 'use strict'; | ||
| */ | ||
| function isRetryableError(error) { | ||
| return error.code !== 'ECONNABORTED' && (!error.response || error.response.status >= 500 && error.response.status <= 599); | ||
| } | ||
| /** | ||
| * @param {Error} error | ||
| * @return {boolean} | ||
| */ | ||
| function isSafeRequestError(error) { | ||
| if (!error.response || !error.config) { | ||
| if (!error.config) { | ||
| // Cannot determine if the request can be retried | ||
| return false; | ||
| } | ||
| return error.response.status >= 500 && error.response.status <= 599 && SAFE_HTTP_METHODS.indexOf(error.config.method) !== -1; | ||
| return isRetryableError(error) && SAFE_HTTP_METHODS.indexOf(error.config.method) !== -1; | ||
| } | ||
@@ -51,7 +60,8 @@ | ||
| function isIdempotentRequestError(error) { | ||
| if (!error.response || !error.config) { | ||
| if (!error.config) { | ||
| // Cannot determine if the request can be retried | ||
| return false; | ||
| } | ||
| return error.response.status >= 500 && error.response.status <= 599 && IDEMPOTENT_HTTP_METHODS.indexOf(error.config.method) !== -1; | ||
| return isRetryableError(error) && IDEMPOTENT_HTTP_METHODS.indexOf(error.config.method) !== -1; | ||
| } | ||
@@ -146,2 +156,8 @@ | ||
| function axiosRetry(axios, defaultOptions) { | ||
| axios.interceptors.request.use(function (config) { | ||
| var currentState = getCurrentState(config); | ||
| currentState.lastRequestTime = Date.now(); | ||
| return config; | ||
| }); | ||
| axios.interceptors.response.use(null, function (error) { | ||
@@ -172,7 +188,7 @@ var config = error.config; | ||
| var now = Date.now(); | ||
| if (config.timeout && currentState.lastRequestTime) { | ||
| config.timeout -= now - currentState.lastRequestTime; | ||
| var lastRequestDuration = Date.now() - currentState.lastRequestTime; | ||
| // Minimum 1ms timeout (passing 0 or less to XHR means no timeout) | ||
| config.timeout = Math.max(config.timeout - lastRequestDuration, 1); | ||
| } | ||
| currentState.lastRequestTime = now; | ||
@@ -179,0 +195,0 @@ return axios(config); |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../es/index.js"],"names":["isNetworkError","isSafeRequestError","isIdempotentRequestError","isNetworkOrIdempotentRequestError","axiosRetry","namespace","error","response","Boolean","code","SAFE_HTTP_METHODS","IDEMPOTENT_HTTP_METHODS","concat","config","status","indexOf","method","getCurrentState","currentState","retryCount","getRequestOptions","defaultOptions","Object","assign","fixConfig","axios","defaults","agent","httpAgent","httpsAgent","interceptors","use","Promise","reject","retries","retryCondition","shouldRetry","now","Date","timeout","lastRequestTime"],"mappings":"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","file":"index.js","sourcesContent":["import isRetryAllowed from 'is-retry-allowed';\n\nconst namespace = 'axios-retry';\n\n/**\n * @param {Error} error\n * @return {boolean}\n */\nexport function isNetworkError(error) {\n return !error.response\n && Boolean(error.code) // Prevents retrying cancelled requests\n && error.code !== 'ECONNABORTED' // Prevents retrying timed out requests\n && isRetryAllowed(error); // Prevents retrying unsafe errors\n}\n\nconst SAFE_HTTP_METHODS = ['get', 'head', 'options'];\nconst IDEMPOTENT_HTTP_METHODS = SAFE_HTTP_METHODS.concat(['put', 'delete']);\n\n/**\n * @param {Error} error\n * @return {boolean}\n */\nexport function isSafeRequestError(error) {\n if (!error.response || !error.config) {\n return false;\n }\n\n return error.response.status >= 500 && error.response.status <= 599\n && SAFE_HTTP_METHODS.indexOf(error.config.method) !== -1;\n}\n\n/**\n * @param {Error} error\n * @return {boolean}\n */\nexport function isIdempotentRequestError(error) {\n if (!error.response || !error.config) {\n return false;\n }\n\n return error.response.status >= 500 && error.response.status <= 599\n && IDEMPOTENT_HTTP_METHODS.indexOf(error.config.method) !== -1;\n}\n\n/**\n * @param {Error} error\n * @return {boolean}\n */\nexport function isNetworkOrIdempotentRequestError(error) {\n return isNetworkError(error) || isIdempotentRequestError(error);\n}\n\n/**\n * Initializes and returns the retry state for the given request/config\n * @param {AxiosRequestConfig} config\n * @return {Object}\n */\nfunction getCurrentState(config) {\n const currentState = config[namespace] || {};\n currentState.retryCount = currentState.retryCount || 0;\n config[namespace] = currentState;\n return currentState;\n}\n\n/**\n * Returns the axios-retry options for the current request\n * @param {AxiosRequestConfig} config\n * @param {AxiosRetryConfig} defaultOptions\n * @return {AxiosRetryConfig}\n */\nfunction getRequestOptions(config, defaultOptions) {\n return Object.assign({}, defaultOptions, config[namespace]);\n}\n\n/**\n * @param {Axios} axios\n * @param {AxiosRequestConfig} config\n */\nfunction fixConfig(axios, config) {\n if (axios.defaults.agent === config.agent) {\n delete config.agent;\n }\n if (axios.defaults.httpAgent === config.httpAgent) {\n delete config.httpAgent;\n }\n if (axios.defaults.httpsAgent === config.httpsAgent) {\n delete config.httpsAgent;\n }\n}\n\n/**\n * Adds response interceptors to an axios instance to retry requests failed due to network issues\n *\n * @example\n *\n * import axios from 'axios';\n *\n * axiosRetry(axios, { retries: 3 });\n *\n * axios.get('http://example.com/test') // The first request fails and the second returns 'ok'\n * .then(result => {\n * result.data; // 'ok'\n * });\n *\n * // Also works with custom axios instances\n * const client = axios.create({ baseURL: 'http://example.com' });\n * axiosRetry(client, { retries: 3 });\n *\n * client.get('/test') // The first request fails and the second returns 'ok'\n * .then(result => {\n * result.data; // 'ok'\n * });\n *\n * // Allows request-specific configuration\n * client\n * .get('/test', {\n * 'axios-retry': {\n * retries: 0\n * }\n * })\n * .catch(error => { // The first request fails\n * error !== undefined\n * });\n *\n * @param {Axios} axios An axios instance (the axios object or one created from axios.create)\n * @param {Object} [defaultOptions]\n * @param {number} [defaultOptions.retries=3] Number of retries\n * @param {number} [defaultOptions.retryCondition=isNetworkOrIdempotentRequestError]\n * A function to determine if the error can be retried\n */\nexport default function axiosRetry(axios, defaultOptions) {\n axios.interceptors.response.use(null, error => {\n const config = error.config;\n\n // If we have no information to retry the request\n if (!config) {\n return Promise.reject(error);\n }\n\n const {\n retries = 3,\n retryCondition = isNetworkOrIdempotentRequestError\n } = getRequestOptions(config, defaultOptions);\n\n const currentState = getCurrentState(config);\n\n const shouldRetry = retryCondition(error)\n && currentState.retryCount < retries;\n\n if (shouldRetry) {\n currentState.retryCount++;\n\n // Axios fails merging this configuration to the default configuration because it has an issue\n // with circular structures: https://github.com/mzabriskie/axios/issues/370\n fixConfig(axios, config);\n\n const now = Date.now();\n if (config.timeout && currentState.lastRequestTime) {\n config.timeout -= now - currentState.lastRequestTime;\n }\n currentState.lastRequestTime = now;\n\n return axios(config);\n }\n\n return Promise.reject(error);\n });\n}\n\n// Compatibility with CommonJS\naxiosRetry.isNetworkError = isNetworkError;\naxiosRetry.isSafeRequestError = isSafeRequestError;\naxiosRetry.isIdempotentRequestError = isIdempotentRequestError;\naxiosRetry.isNetworkOrIdempotentRequestError = isNetworkOrIdempotentRequestError;\n"]} | ||
| {"version":3,"sources":["../es/index.js"],"names":["isNetworkError","isSafeRequestError","isIdempotentRequestError","isNetworkOrIdempotentRequestError","axiosRetry","namespace","error","response","Boolean","code","SAFE_HTTP_METHODS","IDEMPOTENT_HTTP_METHODS","concat","isRetryableError","status","config","indexOf","method","getCurrentState","currentState","retryCount","getRequestOptions","defaultOptions","Object","assign","fixConfig","axios","defaults","agent","httpAgent","httpsAgent","interceptors","request","use","lastRequestTime","Date","now","Promise","reject","retries","retryCondition","shouldRetry","timeout","lastRequestDuration","Math","max"],"mappings":"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","file":"index.js","sourcesContent":["import isRetryAllowed from 'is-retry-allowed';\n\nconst namespace = 'axios-retry';\n\n/**\n * @param {Error} error\n * @return {boolean}\n */\nexport function isNetworkError(error) {\n return !error.response\n && Boolean(error.code) // Prevents retrying cancelled requests\n && error.code !== 'ECONNABORTED' // Prevents retrying timed out requests\n && isRetryAllowed(error); // Prevents retrying unsafe errors\n}\n\nconst SAFE_HTTP_METHODS = ['get', 'head', 'options'];\nconst IDEMPOTENT_HTTP_METHODS = SAFE_HTTP_METHODS.concat(['put', 'delete']);\n\n/**\n * @param {Error} error\n * @return {boolean}\n */\nfunction isRetryableError(error) {\n return error.code !== 'ECONNABORTED'\n && (!error.response || (error.response.status >= 500 && error.response.status <= 599));\n}\n\n/**\n * @param {Error} error\n * @return {boolean}\n */\nexport function isSafeRequestError(error) {\n if (!error.config) {\n // Cannot determine if the request can be retried\n return false;\n }\n\n return isRetryableError(error) && SAFE_HTTP_METHODS.indexOf(error.config.method) !== -1;\n}\n\n/**\n * @param {Error} error\n * @return {boolean}\n */\nexport function isIdempotentRequestError(error) {\n if (!error.config) {\n // Cannot determine if the request can be retried\n return false;\n }\n\n return isRetryableError(error) && IDEMPOTENT_HTTP_METHODS.indexOf(error.config.method) !== -1;\n}\n\n/**\n * @param {Error} error\n * @return {boolean}\n */\nexport function isNetworkOrIdempotentRequestError(error) {\n return isNetworkError(error) || isIdempotentRequestError(error);\n}\n\n/**\n * Initializes and returns the retry state for the given request/config\n * @param {AxiosRequestConfig} config\n * @return {Object}\n */\nfunction getCurrentState(config) {\n const currentState = config[namespace] || {};\n currentState.retryCount = currentState.retryCount || 0;\n config[namespace] = currentState;\n return currentState;\n}\n\n/**\n * Returns the axios-retry options for the current request\n * @param {AxiosRequestConfig} config\n * @param {AxiosRetryConfig} defaultOptions\n * @return {AxiosRetryConfig}\n */\nfunction getRequestOptions(config, defaultOptions) {\n return Object.assign({}, defaultOptions, config[namespace]);\n}\n\n/**\n * @param {Axios} axios\n * @param {AxiosRequestConfig} config\n */\nfunction fixConfig(axios, config) {\n if (axios.defaults.agent === config.agent) {\n delete config.agent;\n }\n if (axios.defaults.httpAgent === config.httpAgent) {\n delete config.httpAgent;\n }\n if (axios.defaults.httpsAgent === config.httpsAgent) {\n delete config.httpsAgent;\n }\n}\n\n/**\n * Adds response interceptors to an axios instance to retry requests failed due to network issues\n *\n * @example\n *\n * import axios from 'axios';\n *\n * axiosRetry(axios, { retries: 3 });\n *\n * axios.get('http://example.com/test') // The first request fails and the second returns 'ok'\n * .then(result => {\n * result.data; // 'ok'\n * });\n *\n * // Also works with custom axios instances\n * const client = axios.create({ baseURL: 'http://example.com' });\n * axiosRetry(client, { retries: 3 });\n *\n * client.get('/test') // The first request fails and the second returns 'ok'\n * .then(result => {\n * result.data; // 'ok'\n * });\n *\n * // Allows request-specific configuration\n * client\n * .get('/test', {\n * 'axios-retry': {\n * retries: 0\n * }\n * })\n * .catch(error => { // The first request fails\n * error !== undefined\n * });\n *\n * @param {Axios} axios An axios instance (the axios object or one created from axios.create)\n * @param {Object} [defaultOptions]\n * @param {number} [defaultOptions.retries=3] Number of retries\n * @param {number} [defaultOptions.retryCondition=isNetworkOrIdempotentRequestError]\n * A function to determine if the error can be retried\n */\nexport default function axiosRetry(axios, defaultOptions) {\n axios.interceptors.request.use((config) => {\n const currentState = getCurrentState(config);\n currentState.lastRequestTime = Date.now();\n return config;\n });\n\n axios.interceptors.response.use(null, error => {\n const config = error.config;\n\n // If we have no information to retry the request\n if (!config) {\n return Promise.reject(error);\n }\n\n const {\n retries = 3,\n retryCondition = isNetworkOrIdempotentRequestError\n } = getRequestOptions(config, defaultOptions);\n\n const currentState = getCurrentState(config);\n\n const shouldRetry = retryCondition(error)\n && currentState.retryCount < retries;\n\n if (shouldRetry) {\n currentState.retryCount++;\n\n // Axios fails merging this configuration to the default configuration because it has an issue\n // with circular structures: https://github.com/mzabriskie/axios/issues/370\n fixConfig(axios, config);\n\n if (config.timeout && currentState.lastRequestTime) {\n const lastRequestDuration = Date.now() - currentState.lastRequestTime;\n // Minimum 1ms timeout (passing 0 or less to XHR means no timeout)\n config.timeout = Math.max(config.timeout - lastRequestDuration, 1);\n }\n\n return axios(config);\n }\n\n return Promise.reject(error);\n });\n}\n\n// Compatibility with CommonJS\naxiosRetry.isNetworkError = isNetworkError;\naxiosRetry.isSafeRequestError = isSafeRequestError;\naxiosRetry.isIdempotentRequestError = isIdempotentRequestError;\naxiosRetry.isNetworkOrIdempotentRequestError = isNetworkOrIdempotentRequestError;\n"]} |
+1
-1
| { | ||
| "name": "axios-retry", | ||
| "version": "3.0.0", | ||
| "version": "3.0.1", | ||
| "author": "Rubén Norte <ruben.norte@softonic.com>", | ||
@@ -5,0 +5,0 @@ "description": "Axios plugin that intercepts failed requests and retries them whenever posible.", |
26258
8.55%339
8.65%