dashboard/shell/utils/axios.js

172 lines
4.2 KiB
JavaScript

import Axios from 'axios';
import defu from 'defu';
import axiosRetry from 'axios-retry';
// Axios.prototype cannot be modified
const axiosExtra = {
setBaseURL(baseURL) {
this.defaults.baseURL = baseURL;
},
setHeader(name, value, scopes = 'common') {
for (const scope of Array.isArray(scopes) ? scopes : [scopes]) {
if (!value) {
delete this.defaults.headers[scope][name];
return;
}
this.defaults.headers[scope][name] = value;
}
},
setToken(token, type, scopes = 'common') {
const value = !token ? null : (type ? `${ type } ` : '') + token;
this.setHeader('Authorization', value, scopes);
},
onRequest(fn) {
this.interceptors.request.use((config) => fn(config) || config);
},
onResponse(fn) {
this.interceptors.response.use((response) => fn(response) || response);
},
onRequestError(fn) {
this.interceptors.request.use(undefined, (error) => fn(error) || Promise.reject(error));
},
onResponseError(fn) {
this.interceptors.response.use(undefined, (error) => fn(error) || Promise.reject(error));
},
onError(fn) {
this.onRequestError(fn);
this.onResponseError(fn);
},
create(options) {
return createAxiosInstance(defu(options, this.defaults));
}
};
// Request helpers ($get, $post, ...)
for (const method of ['request', 'delete', 'get', 'head', 'options', 'post', 'put', 'patch']) {
axiosExtra[`$${ method }`] = function() {
return this[method].apply(this, arguments).then((res) => res && res.data);
};
}
const extendAxiosInstance = (axios) => {
for (const key in axiosExtra) {
axios[key] = axiosExtra[key].bind(axios);
}
};
const createAxiosInstance = (axiosOptions) => {
// Create new axios instance
const axios = Axios.create(axiosOptions);
axios.CancelToken = Axios.CancelToken;
axios.isCancel = Axios.isCancel;
// Extend axios proto
extendAxiosInstance(axios);
// Setup interceptors
setupProgress(axios);
axiosRetry(axios, { retries: 0 });
return axios;
};
const setupProgress = (axios) => {
// A noop loading inteterface for when $loading is not yet ready
const noopLoading = {
finish: () => { },
start: () => { },
fail: () => { },
set: () => { }
};
const $loading = () => {
const $globalApp = window.$globalApp;
return ($globalApp && $globalApp.$loading && $globalApp.$loading.set) ? $globalApp.$loading : noopLoading;
};
let currentRequests = 0;
axios.onRequest((config) => {
if (config && config.progress === false) {
return;
}
currentRequests++;
});
axios.onResponse((response) => {
if (response && response.config && response.config.progress === false) {
return;
}
currentRequests--;
if (currentRequests <= 0) {
currentRequests = 0;
$loading().finish();
}
});
axios.onError((error) => {
if (error && error.config && error.config.progress === false) {
return;
}
currentRequests--;
if (Axios.isCancel(error)) {
return;
}
$loading().fail();
$loading().finish();
});
const onProgress = (e) => {
if (!currentRequests) {
return;
}
const progress = ((e.loaded * 100) / (e.total * currentRequests));
$loading().set(Math.min(100, progress));
};
axios.defaults.onUploadProgress = onProgress;
axios.defaults.onDownloadProgress = onProgress;
};
export default (ctx, inject) => {
// runtimeConfig
const runtimeConfig = (ctx.$config && ctx.$config.axios) || {};
// baseURL
const baseURL = process.browser ? (runtimeConfig.browserBaseURL || runtimeConfig.baseURL || '/') : (runtimeConfig.baseURL || process.env._AXIOS_BASE_URL_ || 'https://localhost:8005/');
// Create fresh objects for all default header scopes
// Axios creates only one which is shared across SSR requests!
// https://github.com/mzabriskie/axios/blob/master/lib/defaults.js
const headers = {
common: { Accept: 'application/json, text/plain, */*' },
delete: {},
get: {},
head: {},
post: {},
put: {},
patch: {}
};
const axiosOptions = {
baseURL,
headers
};
const axios = createAxiosInstance(axiosOptions);
// Inject axios to the context as $axios
ctx.$axios = axios;
inject('axios', axios);
};