request.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. import fetch from 'dva/fetch';
  2. import { message, notification } from 'antd';
  3. import router from 'umi/router';
  4. import hash from 'hash.js';
  5. import { isAntdPro, getToken, GetTokenFromUrl, storeToken } from './utils';
  6. // var apiUrl = "http://oraysmart.com:8888"
  7. // var apiUrl = "http://120.55.44.4:8900"
  8. //节流阀
  9. let flag = false;
  10. let tokenFlag = false;
  11. const checkStatus = response => {
  12. if (response.status >= 200 && response.status < 300) {
  13. return response;
  14. }
  15. // if (
  16. // response.status == 400 ||
  17. // response.status == 401 ||
  18. // response.status == 601 ||
  19. // response.status == 602
  20. // ) {
  21. // response
  22. // .json()
  23. // .then(body => {
  24. // notification.error({
  25. // message: '错误',
  26. // description: `${body.msg}-${body.data}: ${response.url}`,
  27. // });
  28. // })
  29. // .catch(err => {
  30. // notification.error({
  31. // message: '错误',
  32. // description: 'token失效,请重新登录',
  33. // });
  34. // });
  35. // return response;
  36. // }
  37. // if (response.status === 600) {
  38. // return response;
  39. // }
  40. const error = new Error(response.data);
  41. error.name = response.status;
  42. error.response = response;
  43. console.error(error);
  44. // throw error;
  45. return Promise.reject();
  46. };
  47. const cachedSave = response => {
  48. if (response.status === 600) return response;
  49. /**
  50. * Clone a response data and store it in sessionStorage
  51. * Does not support data other than json, Cache only json
  52. */
  53. const contentType = response.headers.get('Content-Type');
  54. if (contentType && contentType.match(/application\/json/i)) {
  55. // All data is saved as text
  56. response
  57. .clone()
  58. .text()
  59. .then(() => {
  60. // sessionStorage.setItem(hashcode, content);
  61. // sessionStorage.setItem(`${hashcode}:timestamp`, Date.now());
  62. });
  63. }
  64. return response;
  65. };
  66. /**
  67. * Requests a URL, returning a promise.
  68. *
  69. * @param {string} url The URL we want to request
  70. * @param {object} [option] The options we want to pass to "fetch"
  71. * @return {object} An object containing either "data" or "err"
  72. */
  73. export default function request(url, option, jwt) {
  74. const number = new Date().getTime();
  75. // console.log(API_HOST);
  76. const time = url.indexOf('?') > -1 ? `&time=${number}` : `?time=${number}`;
  77. if (url.indexOf('http://') == -1 && url.indexOf('https://') == -1) {
  78. if (
  79. url.indexOf('/api/v') === -1 &&
  80. url.indexOf('/api/supplier') === -1 &&
  81. url.indexOf('/api/contract') === -1
  82. ) {
  83. url = `/api/v1${url}${time}`;
  84. }
  85. // API_HOST在config/config.js的define中配置
  86. // url = API_HOST + url
  87. }
  88. console.log(url);
  89. let token = getToken();
  90. if (!token) {
  91. token = GetTokenFromUrl();
  92. storeToken(token);
  93. }
  94. const options = {
  95. expirys: isAntdPro(),
  96. ...option,
  97. };
  98. /**
  99. * Produce fingerprints based on url and parameters
  100. * Maybe url has the same parameters
  101. */
  102. const fingerprint = url + (options.body ? JSON.stringify(options.body) : '');
  103. const hashcode = hash
  104. .sha256()
  105. .update(fingerprint)
  106. .digest('hex');
  107. const defaultOptions = {
  108. credentials: 'include',
  109. };
  110. const newOptions = { ...defaultOptions, ...options };
  111. newOptions.headers = {
  112. ...newOptions.headers,
  113. 'JWT-TOKEN': jwt ? jwt : `${token}`,
  114. };
  115. if (
  116. newOptions.method === 'POST' ||
  117. newOptions.method === 'PUT' ||
  118. newOptions.method === 'DELETE'
  119. ) {
  120. if (!(newOptions.body instanceof FormData)) {
  121. newOptions.headers = {
  122. Accept: 'application/json',
  123. 'Content-Type': 'application/json;charset=utf-8',
  124. ...newOptions.headers,
  125. };
  126. newOptions.body = JSON.stringify(newOptions.body);
  127. } else {
  128. // newOptions.body is FormData
  129. newOptions.headers = {
  130. Accept: 'application/json',
  131. ...newOptions.headers,
  132. };
  133. }
  134. }
  135. const expirys = options.expirys && 60;
  136. // options.expirys !== false, return the cache,
  137. if (options.expirys !== false) {
  138. const cached = sessionStorage.getItem(hashcode);
  139. const whenCached = sessionStorage.getItem(`${hashcode}:timestamp`);
  140. if (cached !== null && whenCached !== null) {
  141. const age = (Date.now() - whenCached) / 1000;
  142. if (age < expirys) {
  143. const response = new Response(new Blob([cached]));
  144. return response.json();
  145. }
  146. sessionStorage.removeItem(hashcode);
  147. sessionStorage.removeItem(`${hashcode}:timestamp`);
  148. }
  149. }
  150. return fetch(url, newOptions)
  151. .then(checkStatus)
  152. .then(response => cachedSave(response, hashcode))
  153. .then(response => {
  154. // DELETE and 204 do not return data by default
  155. // using .json will report an error.
  156. if (response.status === 204) {
  157. return response.text();
  158. }
  159. // if (response.status === 600) {
  160. // return response;
  161. // } else {
  162. return response.json();
  163. // }
  164. })
  165. .then(response => {
  166. let code = response.code;
  167. if (typeof response === 'string') {
  168. return response;
  169. } else if (code !== 200) {
  170. if (code === 401 || code === 601 || code === 602) {
  171. if (tokenFlag) return false;
  172. // 用户token出错,重定向
  173. tokenFlag = true;
  174. setTimeout(() => {
  175. tokenFlag = false;
  176. }, 3000);
  177. notification.error({
  178. message: '错误',
  179. description: 'token失效,请重新登录',
  180. });
  181. router.push(`/login?referrer=${encodeURIComponent(encodeURIComponent(location.href))}`);
  182. } else {
  183. if (flag) return false;
  184. flag = true;
  185. setTimeout(() => {
  186. flag = false;
  187. }, 3000);
  188. message.error(response.msg);
  189. }
  190. return false;
  191. } else {
  192. return response;
  193. }
  194. })
  195. .catch(e => {
  196. const status = e?.name;
  197. // environment should not be used
  198. if (status === 401 || status === 601 || status === 602 || status === 400) {
  199. if (tokenFlag) return false;
  200. // 用户token出错,重定向
  201. tokenFlag = true;
  202. setTimeout(() => {
  203. tokenFlag = false;
  204. }, 3000);
  205. // 用户token出错,重定向
  206. notification.error({
  207. message: '错误',
  208. description: 'token失效,请重新登录',
  209. });
  210. router.push(`/login?referrer=${encodeURIComponent(encodeURIComponent(location.href))}`);
  211. return;
  212. } else if (status == 'AbortError') {
  213. // 中止的ajax 不做额外处理
  214. return e;
  215. }
  216. // if (status <= 504 && status > 500 && status !== 600) {
  217. // router.push('/exception/500');
  218. // throw e;
  219. // }
  220. // if (status >= 404 && status < 422) {
  221. // router.push('/exception/404');
  222. // throw e;
  223. // }
  224. // if (status === 600) {
  225. // throw e;
  226. // }
  227. notification.error({
  228. message: '错误',
  229. description: `网络连接异常,请检查网络后重试`,
  230. // description: `HTTP请求错误,错误码:${status};接口地址${url}`,
  231. });
  232. throw e;
  233. });
  234. }