import fetch from 'dva/fetch'; import { message, notification } from 'antd'; import router from 'umi/router'; import hash from 'hash.js'; import { isAntdPro, getToken, GetTokenFromUrl, storeToken } from './utils'; // var apiUrl = "http://oraysmart.com:8888" // var apiUrl = "http://120.55.44.4:8900" //节流阀 let flag = false; let tokenFlag = false; const checkStatus = response => { if (response.status >= 200 && response.status < 300) { return response; } // if ( // response.status == 400 || // response.status == 401 || // response.status == 601 || // response.status == 602 // ) { // response // .json() // .then(body => { // notification.error({ // message: '错误', // description: `${body.msg}-${body.data}: ${response.url}`, // }); // }) // .catch(err => { // notification.error({ // message: '错误', // description: 'token失效,请重新登录', // }); // }); // return response; // } // if (response.status === 600) { // return response; // } const error = new Error(response.data); error.name = response.status; error.response = response; console.error(error); // throw error; return Promise.reject(); }; const cachedSave = response => { if (response.status === 600) return response; /** * Clone a response data and store it in sessionStorage * Does not support data other than json, Cache only json */ const contentType = response.headers.get('Content-Type'); if (contentType && contentType.match(/application\/json/i)) { // All data is saved as text response .clone() .text() .then(() => { // sessionStorage.setItem(hashcode, content); // sessionStorage.setItem(`${hashcode}:timestamp`, Date.now()); }); } return response; }; /** * Requests a URL, returning a promise. * * @param {string} url The URL we want to request * @param {object} [option] The options we want to pass to "fetch" * @return {object} An object containing either "data" or "err" */ export default function request(url, option, jwt) { const number = new Date().getTime(); // console.log(API_HOST); const time = url.indexOf('?') > -1 ? `&time=${number}` : `?time=${number}`; if (url.indexOf('http://') == -1 && url.indexOf('https://') == -1) { if ( url.indexOf('/api/v') === -1 && url.indexOf('/api/supplier') === -1 && url.indexOf('/api/contract') === -1 ) { url = `/api/v1${url}${time}`; } // API_HOST在config/config.js的define中配置 // url = API_HOST + url } console.log(url); let token = getToken(); if (!token) { token = GetTokenFromUrl(); storeToken(token); } const options = { expirys: isAntdPro(), ...option, }; /** * Produce fingerprints based on url and parameters * Maybe url has the same parameters */ const fingerprint = url + (options.body ? JSON.stringify(options.body) : ''); const hashcode = hash .sha256() .update(fingerprint) .digest('hex'); const defaultOptions = { credentials: 'include', }; const newOptions = { ...defaultOptions, ...options }; newOptions.headers = { ...newOptions.headers, 'JWT-TOKEN': jwt ? jwt : `${token}`, }; if ( newOptions.method === 'POST' || newOptions.method === 'PUT' || newOptions.method === 'DELETE' ) { if (!(newOptions.body instanceof FormData)) { newOptions.headers = { Accept: 'application/json', 'Content-Type': 'application/json;charset=utf-8', ...newOptions.headers, }; newOptions.body = JSON.stringify(newOptions.body); } else { // newOptions.body is FormData newOptions.headers = { Accept: 'application/json', ...newOptions.headers, }; } } const expirys = options.expirys && 60; // options.expirys !== false, return the cache, if (options.expirys !== false) { const cached = sessionStorage.getItem(hashcode); const whenCached = sessionStorage.getItem(`${hashcode}:timestamp`); if (cached !== null && whenCached !== null) { const age = (Date.now() - whenCached) / 1000; if (age < expirys) { const response = new Response(new Blob([cached])); return response.json(); } sessionStorage.removeItem(hashcode); sessionStorage.removeItem(`${hashcode}:timestamp`); } } return fetch(url, newOptions) .then(checkStatus) .then(response => cachedSave(response, hashcode)) .then(response => { // DELETE and 204 do not return data by default // using .json will report an error. if (response.status === 204) { return response.text(); } // if (response.status === 600) { // return response; // } else { return response.json(); // } }) .then(response => { let code = response.code; if (typeof response === 'string') { return response; } else if (code !== 200) { if (code === 401 || code === 601 || code === 602) { if (tokenFlag) return false; // 用户token出错,重定向 tokenFlag = true; setTimeout(() => { tokenFlag = false; }, 3000); notification.error({ message: '错误', description: 'token失效,请重新登录', }); router.push(`/login?referrer=${encodeURIComponent(encodeURIComponent(location.href))}`); } else { if (flag) return false; flag = true; setTimeout(() => { flag = false; }, 3000); message.error(response.msg); } return false; } else { return response; } }) .catch(e => { const status = e?.name; // environment should not be used if (status === 401 || status === 601 || status === 602 || status === 400) { if (tokenFlag) return false; // 用户token出错,重定向 tokenFlag = true; setTimeout(() => { tokenFlag = false; }, 3000); // 用户token出错,重定向 notification.error({ message: '错误', description: 'token失效,请重新登录', }); router.push(`/login?referrer=${encodeURIComponent(encodeURIComponent(location.href))}`); return; } else if (status == 'AbortError') { // 中止的ajax 不做额外处理 return e; } // if (status <= 504 && status > 500 && status !== 600) { // router.push('/exception/500'); // throw e; // } // if (status >= 404 && status < 422) { // router.push('/exception/404'); // throw e; // } // if (status === 600) { // throw e; // } notification.error({ message: '错误', description: `网络连接异常,请检查网络后重试`, // description: `HTTP请求错误,错误码:${status};接口地址${url}`, }); throw e; }); }