yufp.service.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /**
  2. * @created by helin3 on 2017-11-25
  3. * @updated by
  4. * @description 服务访问组件
  5. */
  6. (function (yufp, window, factory) {
  7. var exports = factory(yufp, window, window.document);
  8. if (typeof define === 'function') {
  9. define(exports);
  10. }
  11. window.yufp.service = exports;
  12. }(yufp, window, function (yufp, window, document) {
  13. /**
  14. * 定义Service
  15. * @constructor
  16. */
  17. function Service() {
  18. this.options = {
  19. method: 'POST', // 默认POST,支持4种访问类型 GET/POST/PUT/DELETE
  20. async: true, // 异步请求
  21. data: {}, // 请求数据
  22. headers: {
  23. 'Content-Type': 'application/json; charset=UTF-8'
  24. }, // http请求头
  25. dataType: 'json', // 默认返回数据类型
  26. timeout: 90000, // 默认超时时间
  27. cache: false, // 是否缓存
  28. needToken: true, // 是否传认证Token值去后台
  29. callback: false // 回调方法
  30. };
  31. this._filters = []; // 过滤器集合
  32. this.basePath = ''; // 应用名
  33. this.tokenId = 'Authorization'; // TOKEN 名
  34. this.tokenVal = ''; // TOKEN 值
  35. this.storage = yufp.sessionStorage; // 根据debug模式,存储会话值
  36. this.addServiceFilter();
  37. }
  38. Service.prototype.addServiceFilter = function () {
  39. // 加入请求过滤器
  40. this.addFilter({
  41. // 过滤器名称
  42. name: 'messageParser',
  43. // 请求前触发
  44. before: function (event) {
  45. // 定义请求头
  46. var headers = {};
  47. // 定义请求数据
  48. var reqData = {
  49. // 请求头
  50. headers: headers,
  51. // 请求数据
  52. data: event.data
  53. };
  54. // 保存导出数据
  55. event.code = 0;
  56. event.data = reqData;
  57. // 返回处理标志,true则继续处理,false则中断处理
  58. return true;
  59. },
  60. // 数据返回后触发
  61. after: function (event) {
  62. // 只处理JSON对象
  63. if (yufp.type(event.data) == 'object' && yufp.type(event.data.header) != 'undefined') {
  64. // 获取响应头
  65. var rspHeader = event.data.header;
  66. // 获取响应数据
  67. var rspData = event.data.data;
  68. if (yufp.type(rspHeader.code) == 'undefined' || rspHeader.code == 0) {
  69. // 保存导出数据
  70. event.code = 0;
  71. event.message = '';
  72. event.data = rspData;
  73. // 返回处理标志,true则继续处理,false则中断处理
  74. } else {
  75. // 保存导出数据
  76. event.code = rspHeader.code;
  77. event.message = rspHeader.msg;
  78. event.data = rspData;
  79. // 返回处理标志,true则继续处理,false则中断处理
  80. }
  81. }
  82. // 返回处理标志,true则继续处理,false则中断处理
  83. return true;
  84. },
  85. // HTTP请求异常
  86. exception: function (event) {
  87. var status = event.xhr.status;
  88. var flag = true;
  89. var globalVm = console.log;
  90. switch (status) {
  91. case 401:
  92. var responseUrl = event.requestUrl;
  93. // 服务平台坑(/api/logout注销会在请求头带token,若token已过期,也会走到此处)
  94. if (responseUrl.indexOf(yufp.session.settings.logoutUrl) < 0) {
  95. // 判断非注销服务造成的401,才走此逻辑
  96. yufp.session.logout(true);
  97. }
  98. flag = false;
  99. break;
  100. case 403:
  101. globalVm({
  102. message: '您无权限访问,请联系系统管理员!',
  103. type: 'warning'
  104. });
  105. flag = false;
  106. break;
  107. case 404:
  108. globalVm({
  109. message: '系统错误,请联系系统管理员!',
  110. type: 'error'
  111. });
  112. flag = false;
  113. break;
  114. default:
  115. globalVm({
  116. message: '系统错误,请联系系统管理员!',
  117. type: 'error'
  118. });
  119. flag = false;
  120. break;
  121. }
  122. return flag;
  123. }
  124. });
  125. }
  126. /**
  127. * 发送请求
  128. * @param options
  129. */
  130. // Service.prototype.request = function (options) {
  131. // var _this = this;
  132. // var _options = yufp.extend({}, _this.options, options);
  133. // _options.url = _this.getUrl(_options);
  134. // var deferred = new yufp.core.Deferred();
  135. // var event = {
  136. // data: _options.data
  137. // };
  138. // // before过滤
  139. // if (_this._doFilter(0, event) === false) {
  140. // event.code = event.code ? event.code : 2;
  141. // deferred.reject(event.code, event.message, event.data);
  142. // if (_options.callback) {
  143. // _options.callback(event.code, event.message, event.data);
  144. // }
  145. // return deferred;
  146. // }
  147. // _options.data = event.data.data;
  148. // _options.headers = yufp.extend({}, event.data.headers || {}, _options.headers);
  149. // _options.type = options.method;
  150. // _options.async = options.async;
  151. // _options.success = function (data, status, xhr) {
  152. // // 定义过滤事件
  153. // var event = { code: 0, message: 'success', data: data };
  154. // // after过滤器
  155. // // 过滤器中断调用处理
  156. // if (_this._doFilter(1, event) === false) {
  157. // var code = event.code ? event.code : 1;
  158. // // 通知调用失败
  159. // deferred.reject(code, event.message, event.data);
  160. // if (_options.callback) {
  161. // _options.callback(code, event.message, event.data);
  162. // }
  163. // return;
  164. // }
  165. // // 通知调用成功
  166. // deferred.resolve(event.code, event.message, event.data);
  167. // if (_options.callback) {
  168. // _options.callback(event.code, event.message, event.data);
  169. // }
  170. // };
  171. // _options.error = function (xhr, status) {
  172. // var msg = xhr.responseText;
  173. // msg = !msg ? status : msg;
  174. // // 定义过滤事件
  175. // var event = { code: 1, message: msg, xhr: xhr, requestUrl: _options.url };
  176. // // exception过滤
  177. // if (_this._doFilter(2, event) === false) {
  178. // // 通知调用失败
  179. // deferred.reject(event.code, event.message, event.data);
  180. // return;
  181. // }
  182. // event.code = event.code ? event.code : 1;
  183. // // 通知调用失败
  184. // deferred.reject(event.code, event.message, event.data);
  185. // // 判断是否存在回调函数
  186. // if (_options.callback) {
  187. // _options.callback(event.code, event.message, event.data);
  188. // }
  189. // };
  190. // yufp.core.ajax(_options);
  191. // };
  192. /**
  193. * 获取最终访问的完整URL
  194. * @param param {url }
  195. * @returns {string}
  196. */
  197. Service.prototype.getUrl = function (param) {
  198. var paramUrl = param.url || param.name;
  199. if (!paramUrl) {
  200. throw new Error('Yufp.service.request: 未设置请求URL');
  201. }
  202. var reg = /^(http|https):\/\//;
  203. // url请求未附带http(s)://前缀,则按yufp.settings.url及ssl添加前缀
  204. if (!reg.test(paramUrl)) {
  205. var protocol, prefixUrl = '';
  206. // yufp.settings.url 非空,即非默认同源模式,计算服务端URL源路径
  207. if (prefixUrl) {
  208. protocol = reg.test(prefixUrl) ? '' : yufp.settings.ssl ? 'https://' : 'http://';
  209. prefixUrl = protocol + prefixUrl;
  210. }
  211. paramUrl = ('/' + paramUrl).replace(/^\/\//, '/'); // 添加前缀
  212. paramUrl = (this.basePath || '') + paramUrl; // 添加basePath
  213. paramUrl = prefixUrl + paramUrl; // 组合origin
  214. }
  215. return paramUrl;
  216. };
  217. /**
  218. * 存储token信息
  219. * @param {object|string} token 对象
  220. * { access_token: '', refresh_token: '', expires_in: '' }
  221. */
  222. Service.prototype.putToken = function (tokenObj) {
  223. if (typeof tokenObj == 'object') {
  224. var currentTime = new Date().getTime(); // 当前时间
  225. // 记录 access_token 时间(相对于浏览器客户端来说),默认减去1min中
  226. tokenObj.buildTime = currentTime - 60000; // 单位:毫秒
  227. }
  228. this.storage.put('UFP-' + this.tokenId, tokenObj);
  229. };
  230. /**
  231. * 获取token信息,可能会触发refreshToken方法
  232. * refresh_token无效时,access_token返回空串
  233. */
  234. Service.prototype.getToken = function () {
  235. var _this = this;
  236. var tokenObj = this.storage.get('UFP-' + this.tokenId) || '';
  237. var currentTime = new Date().getTime(); // 当前时间
  238. if (tokenObj.expires_in && (currentTime - tokenObj.buildTime) / 1000 > tokenObj.expires_in) {
  239. // access_token 已失效,通过refresh_token 同步ajax请求重新获取;
  240. tokenObj = _this.refreshToken(tokenObj);
  241. if (tokenObj) {
  242. _this.putToken(tokenObj);
  243. }
  244. return tokenObj ? tokenObj.access_token : '';
  245. } else {
  246. // access_token 未失效,正常获取使用
  247. return tokenObj.access_token;
  248. }
  249. };
  250. /**
  251. * 移除token信息
  252. */
  253. Service.prototype.removeToken = function () {
  254. this.storage.remove('UFP-' + this.tokenId);
  255. };
  256. /**
  257. * 通过refresh_token,同步ajax请求重新获取相关token信息
  258. * @param {object|string} token 对象
  259. * { access_token: '', refresh_token: '', expires_in: '' }
  260. */
  261. Service.prototype.refreshToken = function (tokenObj) {
  262. var returnTokenObj;
  263. yufp.service.request({
  264. needToken: false,
  265. async: false, // 同步请求
  266. url: backend.uaaService + '/oauth/token',
  267. method: 'post',
  268. headers: {
  269. 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
  270. 'Authorization': 'Basic d2ViX2FwcDo='
  271. },
  272. data: {
  273. 'grant_type': 'refresh_token',
  274. 'refresh_token': tokenObj.refresh_token
  275. },
  276. callback: function (code, message, response) {
  277. if (response && response.access_token) {
  278. // 刷新相关token请求成功
  279. returnTokenObj = {
  280. 'access_token': response.access_token,
  281. 'refresh_token': response.refresh_token,
  282. 'expires_in': response.expires_in
  283. };
  284. } else {
  285. // 刷新相关token请求失败, 跳转至登录页
  286. yufp.session.logout(true);
  287. }
  288. }
  289. });
  290. return returnTokenObj;
  291. };
  292. /**
  293. * 添加服务请求过滤器
  294. * @param {*} obj 过滤器对象
  295. */
  296. Service.prototype.addFilter = function (obj) {
  297. if (typeof obj != 'object') {
  298. yufp.logger.error('filter args must been json object');
  299. return;
  300. }
  301. if (!obj.name) {
  302. yufp.logger.error('filter args must have name attribute');
  303. return;
  304. }
  305. if (!obj.before || typeof obj.before !== 'function') {
  306. yufp.logger.error('filter args must have before function');
  307. return;
  308. }
  309. if (!obj.after || typeof obj.after !== 'function') {
  310. yufp.logger.error('filter args must have after function');
  311. return;
  312. }
  313. if (!obj.exception || typeof obj.exception !== 'function') {
  314. yufp.logger.error('filter args must have exception function');
  315. return;
  316. }
  317. this._filters.push(obj);
  318. };
  319. /**
  320. * 移除服务请求过滤器
  321. * @param {*} obj 过滤器对象
  322. */
  323. Service.prototype.removeFilter = function (obj) {
  324. var name = typeof obj == 'string' ? obj : obj.name;
  325. var i = 0;
  326. for (; i < this._filters.length; i++) {
  327. if (name == this._filters[i].name) {
  328. break;
  329. }
  330. }
  331. if (i < this._filters.length) {
  332. this._filters.splice(i, 1);
  333. }
  334. };
  335. /**
  336. * 执行过滤
  337. * @param {*} type 过滤类型
  338. * @param {*} event 过滤事件参数
  339. */
  340. Service.prototype._doFilter = function (type, event) {
  341. var fname = 'exception';
  342. fname = type == 0 ? 'before' : fname;
  343. fname = type == 1 ? 'after' : fname;
  344. for (var i = 0; i < this._filters.length; i++) {
  345. if (!this._filters[i][fname]) {
  346. continue;
  347. }
  348. var res = this._filters[i][fname](event);
  349. if (res === false) {
  350. return false;
  351. }
  352. }
  353. };
  354. var req = new Service();
  355. Service.prototype.request = function (options){
  356. var _this = req;
  357. var _options = yufp.extend({}, _this.options, options);
  358. _options.url = _this.getUrl(_options);
  359. var deferred = new yufp.core.Deferred();
  360. var event = {
  361. data: _options.data
  362. };
  363. // before过滤
  364. if (_this._doFilter(0, event) === false) {
  365. event.code = event.code ? event.code : 2;
  366. deferred.reject(event.code, event.message, event.data);
  367. if (_options.callback) {
  368. _options.callback(event.code, event.message, event.data);
  369. }
  370. return deferred;
  371. }
  372. _options.data = event.data.data;
  373. _options.headers = yufp.extend({}, event.data.headers || {}, _options.headers);
  374. _options.type = options.method;
  375. _options.async = options.async;
  376. _options.success = function (data, status, xhr) {
  377. // 定义过滤事件
  378. var event = { code: 0, message: 'success', data: data };
  379. // after过滤器
  380. // 过滤器中断调用处理
  381. if (_this._doFilter(1, event) === false) {
  382. var code = event.code ? event.code : 1;
  383. // 通知调用失败
  384. deferred.reject(code, event.message, event.data);
  385. if (_options.callback) {
  386. _options.callback(code, event.message, event.data);
  387. }
  388. return;
  389. }
  390. // 通知调用成功
  391. deferred.resolve(event.code, event.message, event.data);
  392. if (_options.callback) {
  393. _options.callback(event.code, event.message, event.data);
  394. }
  395. };
  396. _options.error = function (xhr, status) {
  397. var msg = xhr.responseText;
  398. msg = !msg ? status : msg;
  399. // 定义过滤事件
  400. var event = { code: 1, message: msg, xhr: xhr, requestUrl: _options.url };
  401. // exception过滤
  402. if (_this._doFilter(2, event) === false) {
  403. // 通知调用失败
  404. deferred.reject(event.code, event.message, event.data);
  405. return;
  406. }
  407. event.code = event.code ? event.code : 1;
  408. // 通知调用失败
  409. deferred.reject(event.code, event.message, event.data);
  410. // 判断是否存在回调函数
  411. if (_options.callback) {
  412. _options.callback(event.code, event.message, event.data);
  413. }
  414. };
  415. yufp.core.ajax(_options);
  416. }
  417. return req;
  418. }));