| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- /** 默认头信息 */
- const DEFAULT_HEAD = {
- 'Content-Type': 'application/json',
- 'Accept-Charset': 'utf-8',
- /** 为解决跨域问题 */
- 'Origin': '*'
- };
- type HTTPRequestMethod = "CONNECT" | "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "TRACE";
- const HREQM: { [key in HTTPRequestMethod]: string } = {
- CONNECT: 'lightslategray',
- HEAD: 'cadetblue',
- OPTIONS: 'thistle',
- GET: 'lightgreen',
- PUT: 'darkcyan',
- DELETE: 'lightcoral',
- POST: 'deepskyblue',
- PATCH: 'silver',
- TRACE: 'steelblue',
- }
- /**
- * 创建请求头
- * @param conf
- */
- function createHeader(conf?: { [field: string]: string }) {
- let header = new Headers();
- [DEFAULT_HEAD, conf].forEach(list => {
- if (!list || list == null) return void 0;
- for (let field in list) header.append(field, Reflect.get(list, field));
- });
- return header;
- }
- /**
- * 格式化请求数据
- * @param param 请求数据
- * @param type 格式类型
- */
- function FormateData(param: { [name: string]: string | number }, type: 'json' | 'form' | 'search') {
- let data: string | FormData;
- if (type === 'json') data = JSON.stringify(param);
- else if (type === 'search') {
- let arr = [];
- for (let name in param) arr.push(`${name}=${param[name]}`);
- data = arr.join('&');
- } else if (type === 'form') {
- data = new FormData();
- for (let name in param) data.set(name, String(param[name]));
- }
- return data;
- }
- /**
- * 创建一个请求对象
- * @param url 请求路径
- * @param data 请求参数
- * @param method 请求方法类型
- * @param head 请求头配置
- */
- function createRequest(url: string, data: any, method?: HTTPRequestMethod, head?: { [name: string]: string }) {
- let body = FormateData(data, 'json');
- let options: RequestInit = {
- method: method ?? "GET",
- headers: createHeader(head)
- }
- if (options.method == 'POST') options.body = body;
- let request = new Request(url, options);
- return request;
- }
- /** 向服务器发送请求 */
- export async function http_send(...args: Parameters<typeof createRequest>) {
- args[2] = args[2] ?? 'GET';
- let req_token = mtec.string.randomToken(8, 36, t => !tokan_map.has(t));
- tokan_map.set(req_token, tokan_map.size);
- // mtec.log.tag([
- // ['SERVICE', 'slategray'],
- // [args[2], Reflect.get(HREQM, args[2])],
- // ['>>', 'dodgerblue']
- // ].map(_=>_.join(':')).join(';'), args[0].split('/').slice(3).join('/'), '\n--------------\nHEADERS:', args[3], '\nDATA:', args[1], '\n--------------\n');
- let start_date = new Date();
- let response: Response;
- let delay = 0;
- let data: any;
- let try_count = 0;
- while (!response?.ok && try_count < 3) {
- response = await fetch(createRequest(...args))
- .then(res => res)
- .catch(err => {
- // console.log('请求失败信息', JSON.stringify(err));
- log_response('单次请求失败', req_token, args[0], start_date, delay, try_count, data, -100, undefined);
- return void 0;
- });
- delay = Date.now() - start_date.valueOf();
- data = response?.ok ? await response.json() : undefined;
- try_count++;
- if (response && response.ok) {
- } else {
- __exception_call_list__.forEach(call => call(req_token, try_count, delay, response?.status ?? -101));
- }
- }
- if (try_count > 1) {
- log_response('触发接口重试', req_token, args[0], start_date, delay, try_count, data, response?.status ?? -102, response);
- __exception_call_list__.forEach(call => call(req_token, try_count, delay, response?.status ?? -102));
- } else if (delay > 5000) {
- log_response('请求延迟过高', req_token, args[0], start_date, delay, try_count, data, response?.status ?? -103, response);
- __exception_call_list__.forEach(call => call(req_token, try_count, delay, response?.status ?? -103));
- }
- if (!response?.ok) {
- log_response('异常接口最终信息', req_token, args[0], start_date, delay, try_count, data, response?.status ?? -104, response);
- __exception_call_list__.forEach(call => call(req_token, try_count, delay, response?.status ?? -104));
- }
- mtec.log.tag([
- ['SERVICE', 'slategray'],
- [args[2], Reflect.get(HREQM, args[2])],
- ['<<', 'seagreen'],
- data ? ['OK', 'springgreen'] : ['ERR', 'red'],
- [delay + ' ms', 'silver']
- ].map(_ => _.join(':')).join(';'), args[0].split('/').slice(3).join('/'), '\n--------------\nRESPONSE:', response, '\nDATA:', data, '\n--------------\n');
- tokan_map.delete(req_token);
- return data;
- }
- type __exception_call__ = (token: string, try_count: number, delay: number, status: number) => void;
- const __exception_call_list__: Array<__exception_call__> = [];
- const tokan_map: Map<string, number> = new Map();
- export function on_network_exception(call: __exception_call__) {
- __exception_call_list__.push(call);
- }
- function log_response(tag: string, token: string, url: string, start_date: Date, delay: number, try_count: number, data: any, status: number, response: Response) {
- // console.log(tag,
- // '\n请求接口: '+url,
- // '\n请求Token: '+token,
- // '\n请求时间: '+start_date.toLocaleString(),
- // '\n请求延迟: '+delay+' ms',
- // '\n请求次数: '+try_count,
- // '\n请求数据: '+JSON.stringify(data),
- // '\n请求状态: '+status,
- // '\n请求结果[Response]: '+JSON.stringify(response)
- // );
- }
|