1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
import axios from 'axios'
import {baseUrl, dataSources} from './env';
import datas from '../data/data';
import { getAccessToken, getRefreshToken } from '../utils/cache.js';
import { Dialog } from 'vant';
import {setLoginToken} from "../utils/cache";
const serviceRouter = function(requestUrl) {
function getConfig() {
const configDev = {
'/order-api': {
prefix: '/order-api',
target: 'http://127.0.0.1:18088/order-api',
},
'/user-api': {
prefix: '/user-api',
target: 'http://127.0.0.1:18082/user-api',
},
'/product-api': {
prefix: '/product-api',
target: 'http://127.0.0.1:18081/product-api',
},
'/promotion-api': {
prefix: '/promotion-api',
target: 'http://127.0.0.1:18085/promotion-api',
},
'/pay-api': {
prefix: '/pay-api',
target: 'http://127.0.0.1:18084/pay-api',
},
'/search-api': {
prefix: '/search-api',
target: 'http://127.0.0.1:18086/search-api',
},
};
const configProd = {
'/order-api': {
prefix: '/order-api',
target: 'http://api.shop.iocoder.cn/order-api',
},
'/user-api': {
prefix: '/user-api',
target: 'http://api.shop.iocoder.cn/user-api',
},
'/product-api': {
prefix: '/product-api',
target: 'http://api.shop.iocoder.cn/product-api',
},
'/promotion-api': {
prefix: '/promotion-api',
target: 'http://api.shop.iocoder.cn/promotion-api',
},
'/pay-api': {
prefix: '/pay-api',
target: 'http://api.shop.iocoder.cn/pay-api',
},
'/search-api': {
prefix: '/search-api',
target: 'http://api.shop.iocoder.cn/search-api',
},
};
if (process.env.NODE_ENV == 'development') {
return configDev;
} else {
return configProd
}
}
// function doCreateServer(config) {
// // 获取请求配置文件
// const createServer = {};
// for (const configKey in config) {
// const serverPrefix = configKey;
// const {target} = config[configKey];
// // 创建服务
// createServer[serverPrefix] = axios.create({
// baseURL: target, // api 的 base_url
// timeout: 5000, // request timeout
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
// }
// });
// }
// }
const config = getConfig();
// TODO 芋艿,临时加下。
// const createServer = doCreateServer(config);
const indexOf = requestUrl.indexOf("/", 1);
const _urlPrefix = requestUrl.substring(0, indexOf);
if (!config[_urlPrefix]) {
// throw new Error(`服务路由,未找到可用服务! ${requestUrl}`);
console.error(`服务路由,未找到可用服务! ${requestUrl}`)
return ''
}
// if (!createServer[_urlPrefix]) {
// throw new Error("服务路由,未找到可用服务!");
// }
// const { target } = config[_urlPrefix];
// const requestServer = createServer[_urlPrefix];
// const targetRequestUrl = _requestUrl.replace(_urlPrefix, target)
// return createServer;
return config[_urlPrefix];
};
const service = axios.create({
// baseURL: baseUrl, // api 的 base_url
timeout: 30000, // request timeout
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
});
const servicef = function (parameter) {
// debugger;
if (dataSources == 'local') {
//定义回调函数和axios一致
const promist = new Promise(function (resolve, reject) {
var data = datas[parameter.url];
if (typeof data == 'string') {
data = JSON.parse(data);
}
resolve(data);
});
return promist;
}
// 设置 access token
// debugger;
// if (getAccessToken()) {
// parameter.headers = {
// ...parameter.headers,
// 'Authorization': `Bearer ${getAccessToken()}`,
// };
// }
// debugger;
return service(parameter);
};
service.interceptors.request.use(
config => {
// 记录下原始请求的地址
config.originUrl = config.url;
// Do something before request is sent
// if (store.getters.token) {
// // 让每个请求携带token-- ['X-Token']为自定义key 请根据实际情况自行修改
// config.headers['X-Token'] = getToken()
// }
// 切换地址
const { target, prefix } = serviceRouter(config.url)
let url = config.url = config.url.replace(`${prefix}`, target);
// TODO 芋艿,这些 url 不用增加认证 token 。可能这么写,有点脏,后面看看咋优化下。
if (url.indexOf('user-api/users/passport/mobile/send_register_code') !== -1
|| url.indexOf('user-api/users/passport/mobile/register') !== -1
|| url.indexOf('user-api/users/passport/refresh_token') !== -1) {
return config;
}
// debugger;
if (getAccessToken()) {
config.headers['Authorization'] = `Bearer ${getAccessToken()}`;
}
return config
},
error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
}
);
function refreshToken(lastResponse) {
// TODO 芋艿,可能会存在多个异步 callback 的情况。
let refreshToken = getRefreshToken();
return servicef({
url: '/user-api/users/passport/refresh_token',
method: 'post',
params: {
refreshToken
}
}).then(data => {
// 设置新的 accessToken
setLoginToken(data.accessToken, data.refreshToken);
// 重新发起请求
let config = lastResponse.config;
return servicef({
url: config.originUrl,
method: config.method,
params: {
...config.params,
}
});
});
}
// response interceptor
service.interceptors.response.use(
//response => response,
/**
* 下面的注释为通过在response里,自定义code来标示请求状态
* 当code返回如下情况则说明权限有问题,登出并返回到登录页
* 如想通过 xmlhttprequest 来状态码标识 逻辑可写在下面error中
* 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除
*/
response => {
// debugger;
const res = response.data;
const code = res.code;
if (code !== 0) {
// // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// // 请自行在引入 MessageBox
// // import { Message, MessageBox } from 'element-ui'
// MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
// confirmButtonText: '重新登录',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
// store.dispatch('FedLogOut').then(() => {
// location.reload() // 为了重新实例化vue-router对象 避免bug
// })
// })
// }
// TODO token 过期
// TODO 需要拿 refresh token 置换
if (code === 1002001011 // 访问令牌不存在
|| code === 1002001013 // 访问令牌已失效
|| code === 1002001017 // 刷新令牌不存在
|| code === 1002001018 // 刷新令牌已过期
|| code === 1002001019) { // 刷新令牌已失效
Dialog.confirm({
title: '系统提示',
message: res.message,
confirmButtonText: '重新登陆',
beforeClose: function (action, done) {
done();
if (action === 'confirm') {
// debugger;
// this.$router.push({ path: '/login' })
// TODO 跳转到登陆页.不是很优雅
location.replace('/#login');
location.reload();
}
}
});
} else if (code === 1002001012) { // 访问令牌已过期
return refreshToken(response);
} else {
Dialog.alert({
title: '系统提示',
message: res.message,
});
}
return Promise.reject('error')
} else {
// if (typeof response.data.Tag == 'string') {
// return JSON.parse(response.data.Tag);
// } else {
// return response.data.Tag;
// }
// debugger;
return res.data;
}
},
error => {
Dialog.alert({
title: '系统提示',
message: error,
});
console.error(`请求失败`, error);
throw new Error(error);
// return Promise.reject(error)
}
);
export default servicef