@deppon/deppon-request 2.4.23 → 2.4.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 识别 HTTP 200 下常见「业务失败」响应体(保守规则,减少误报)。
3
+ * @returns {{ message: string } | null}
4
+ */
5
+ export function detectAxiosBusinessFailure(resData: any): {
6
+ message: string;
7
+ } | null;
8
+ /**
9
+ * @param {*} errorLike deppon 响应拦截器 reject 的 errorInfo,或 axios 错误对象
10
+ */
11
+ export function reportDepponHttpErrorToMonitor(errorLike: any): void;
@@ -0,0 +1,181 @@
1
+ import './_virtual/_rollup-plugin-inject-process-env.js';
2
+ import _typeof from '@babel/runtime/helpers/typeof';
3
+
4
+ /**
5
+ * 当页面已通过 @deppon/deppon-monitor-browser 初始化 Monitor 时,
6
+ * 将 @deppon/deppon-request(axios)链路中的接口错误上报到同一套监控通道。
7
+ * 与 Monitor 在 window 上注册的桥接函数解耦,避免 deppon-request 依赖 monitor 包。
8
+ */
9
+
10
+ var HTTP_ERROR_TYPE = 'HTTP_ERROR';
11
+ function safeStringify(data, maxLen) {
12
+ var max = typeof maxLen === 'number' ? maxLen : 8000;
13
+ try {
14
+ var s = typeof data === 'string' ? data : JSON.stringify(data);
15
+ return s.length > max ? s.slice(0, max) + '...(truncated)' : s;
16
+ } catch (_e) {
17
+ return '';
18
+ }
19
+ }
20
+ function generateTraceId() {
21
+ try {
22
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
23
+ return crypto.randomUUID();
24
+ }
25
+ } catch (_e) {
26
+ /* noop */
27
+ }
28
+ return 'trace-' + Date.now() + '-' + Math.random().toString(36).slice(2, 11);
29
+ }
30
+ function pageHref() {
31
+ return typeof window !== 'undefined' && window.location ? window.location.href : '';
32
+ }
33
+ function shouldIgnoreRequestUrl(url) {
34
+ if (typeof window === 'undefined' || !url) {
35
+ return false;
36
+ }
37
+ var fn = window.__DEPPON_MONITOR_SHOULD_IGNORE_REQUEST_URL__;
38
+ if (typeof fn === 'function') {
39
+ try {
40
+ return fn(url) === true;
41
+ } catch (_e) {
42
+ return false;
43
+ }
44
+ }
45
+ return false;
46
+ }
47
+ function buildFullRequestUrl(req) {
48
+ if (!req) {
49
+ return '';
50
+ }
51
+ var raw = req.url || '';
52
+ if (raw.startsWith('http://') || raw.startsWith('https://')) {
53
+ return raw;
54
+ }
55
+ var base = req.baseURL || '';
56
+ if (!base) {
57
+ return raw;
58
+ }
59
+ return String(base).replace(/\/$/, '') + '/' + String(raw).replace(/^\//, '');
60
+ }
61
+ function buildPayloadFromDepponErrorInfo(errorLike) {
62
+ if (!errorLike || _typeof(errorLike) !== 'object') {
63
+ return null;
64
+ }
65
+ var req = errorLike.request;
66
+ if (req && _typeof(req) === 'object' && typeof req.url === 'string') {
67
+ var url = buildFullRequestUrl(req);
68
+ return {
69
+ type: HTTP_ERROR_TYPE,
70
+ time: Date.now(),
71
+ name: 'HTTP Error',
72
+ message: errorLike.statusText || String(errorLike.status || '') || '请求失败',
73
+ url: pageHref(),
74
+ request: {
75
+ method: (req.method || 'GET').toString().toUpperCase(),
76
+ url: url || req.url,
77
+ data: req.data,
78
+ httpType: 'axios',
79
+ traceId: generateTraceId()
80
+ },
81
+ response: {
82
+ status: typeof errorLike.status === 'number' ? errorLike.status : 0,
83
+ data: safeStringify(errorLike.response !== undefined ? errorLike.response : '')
84
+ }
85
+ };
86
+ }
87
+ return null;
88
+ }
89
+ function buildPayloadFromAxiosError(errorLike) {
90
+ if (!errorLike || _typeof(errorLike) !== 'object') {
91
+ return null;
92
+ }
93
+ var cfg = errorLike.config || {};
94
+ var url = buildFullRequestUrl(cfg);
95
+ var status = errorLike.response && typeof errorLike.response.status === 'number' ? errorLike.response.status : 0;
96
+ var resData = errorLike.response && errorLike.response.data;
97
+ var message = errorLike.message || errorLike.code || (status ? String(status) : '') || '网络异常';
98
+ return {
99
+ type: HTTP_ERROR_TYPE,
100
+ time: Date.now(),
101
+ name: 'HTTP Error',
102
+ message: message,
103
+ url: pageHref(),
104
+ request: {
105
+ method: (cfg.method || 'GET').toString().toUpperCase(),
106
+ url: url,
107
+ data: cfg.data,
108
+ httpType: 'axios',
109
+ traceId: generateTraceId()
110
+ },
111
+ response: {
112
+ status: status,
113
+ data: safeStringify(resData !== undefined ? resData : errorLike.message || '')
114
+ }
115
+ };
116
+ }
117
+
118
+ /**
119
+ * 识别 HTTP 200 下常见「业务失败」响应体(保守规则,减少误报)。
120
+ * @returns {{ message: string } | null}
121
+ */
122
+ function detectAxiosBusinessFailure(resData) {
123
+ if (resData == null || _typeof(resData) !== 'object') {
124
+ return null;
125
+ }
126
+ if (resData.success === false) {
127
+ return {
128
+ message: String(resData.message || resData.msg || resData.error || 'success: false')
129
+ };
130
+ }
131
+ if (resData.result === false) {
132
+ return {
133
+ message: String(resData.message || resData.msg || resData.error || 'result: false')
134
+ };
135
+ }
136
+ var c = resData.code;
137
+ if (typeof c === 'number' && c !== 0 && c !== 200) {
138
+ return {
139
+ message: "".concat(String(resData.message || resData.msg || resData.error || '业务错误'), " (code=").concat(c, ")")
140
+ };
141
+ }
142
+ if (typeof c === 'string' && c.length > 0 && c !== '0' && c !== '200') {
143
+ if (/^[45][0-9]{2}$/.test(c)) {
144
+ return {
145
+ message: "".concat(String(resData.message || resData.msg || resData.error || '业务错误'), " (code=").concat(c, ")")
146
+ };
147
+ }
148
+ }
149
+ return null;
150
+ }
151
+
152
+ /**
153
+ * @param {*} errorLike deppon 响应拦截器 reject 的 errorInfo,或 axios 错误对象
154
+ */
155
+ function reportDepponHttpErrorToMonitor(errorLike) {
156
+ if (typeof window === 'undefined') {
157
+ return;
158
+ }
159
+ var report = window.__DEPPON_MONITOR_REPORT_HTTP_ERROR__;
160
+ if (typeof report !== 'function') {
161
+ return;
162
+ }
163
+ var payload = buildPayloadFromDepponErrorInfo(errorLike);
164
+ if (!payload) {
165
+ payload = buildPayloadFromAxiosError(errorLike);
166
+ }
167
+ if (!payload) {
168
+ return;
169
+ }
170
+ var reqUrl = payload.request && payload.request.url;
171
+ if (shouldIgnoreRequestUrl(reqUrl)) {
172
+ return;
173
+ }
174
+ try {
175
+ report(payload);
176
+ } catch (_e) {
177
+ /* noop */
178
+ }
179
+ }
180
+
181
+ export { detectAxiosBusinessFailure, reportDepponHttpErrorToMonitor };
@@ -1,5 +1,6 @@
1
1
  import '../_virtual/_rollup-plugin-inject-process-env.js';
2
2
  import _typeof from '@babel/runtime/helpers/typeof';
3
+ import { detectAxiosBusinessFailure, reportDepponHttpErrorToMonitor } from '../monitorBridge.js';
3
4
 
4
5
  function ResponseInterceptor(res, options) {
5
6
  var resCode = res.status;
@@ -72,7 +73,8 @@ function ResponseInterceptor(res, options) {
72
73
  response: res.data,
73
74
  // 请求信息(从 config 中获取,包含完整的 headers,包括 cookie)
74
75
  request: {
75
- url: ((_res$config3 = res.config) === null || _res$config3 === void 0 ? void 0 : _res$config3.url) || ((_res$config4 = res.config) === null || _res$config4 === void 0 ? void 0 : _res$config4.baseURL) || '',
76
+ url: ((_res$config3 = res.config) === null || _res$config3 === void 0 ? void 0 : _res$config3.url) || '',
77
+ baseURL: ((_res$config4 = res.config) === null || _res$config4 === void 0 ? void 0 : _res$config4.baseURL) || '',
76
78
  method: ((_res$config5 = res.config) === null || _res$config5 === void 0 || (_res$config5 = _res$config5.method) === null || _res$config5 === void 0 ? void 0 : _res$config5.toUpperCase()) || 'GET',
77
79
  params: ((_res$config6 = res.config) === null || _res$config6 === void 0 ? void 0 : _res$config6.params) || {},
78
80
  data: ((_res$config7 = res.config) === null || _res$config7 === void 0 ? void 0 : _res$config7.data) || {},
@@ -81,9 +83,31 @@ function ResponseInterceptor(res, options) {
81
83
  timeout: (_res$config8 = res.config) === null || _res$config8 === void 0 ? void 0 : _res$config8.timeout
82
84
  }
83
85
  };
86
+ reportDepponHttpErrorToMonitor(errorInfo);
84
87
  return Promise.reject(errorInfo);
85
88
  };
86
89
  if (resSuccess) {
90
+ if (typeof window !== 'undefined' && window.__DEPPON_MONITOR_REPORT_AXIOS_BUSINESS__ === true) {
91
+ var biz = detectAxiosBusinessFailure(resData);
92
+ if (biz) {
93
+ var _res$config9, _res$config0, _res$config1, _res$config10, _res$config11, _res$config12;
94
+ var businessErrorInfo = {
95
+ status: res.status,
96
+ statusText: biz.message,
97
+ response: resData,
98
+ request: {
99
+ url: ((_res$config9 = res.config) === null || _res$config9 === void 0 ? void 0 : _res$config9.url) || '',
100
+ baseURL: ((_res$config0 = res.config) === null || _res$config0 === void 0 ? void 0 : _res$config0.baseURL) || '',
101
+ method: ((_res$config1 = res.config) === null || _res$config1 === void 0 || (_res$config1 = _res$config1.method) === null || _res$config1 === void 0 ? void 0 : _res$config1.toUpperCase()) || 'GET',
102
+ params: ((_res$config10 = res.config) === null || _res$config10 === void 0 ? void 0 : _res$config10.params) || {},
103
+ data: ((_res$config11 = res.config) === null || _res$config11 === void 0 ? void 0 : _res$config11.data) || {},
104
+ headers: {},
105
+ timeout: (_res$config12 = res.config) === null || _res$config12 === void 0 ? void 0 : _res$config12.timeout
106
+ }
107
+ };
108
+ reportDepponHttpErrorToMonitor(businessErrorInfo);
109
+ }
110
+ }
87
111
  // 如果没有 success 字段,直接返回数据(兼容没有 success 字段的接口)
88
112
  return Promise.resolve(resData);
89
113
  } else {
@@ -91,6 +115,7 @@ function ResponseInterceptor(res, options) {
91
115
  }
92
116
  }
93
117
  function ResponseInterceptorError(res, options) {
118
+ reportDepponHttpErrorToMonitor(res);
94
119
  return Promise.reject(res);
95
120
  }
96
121
  var res = ResponseInterceptor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deppon/deppon-request",
3
- "version": "2.4.23",
3
+ "version": "2.4.24",
4
4
  "description": "Frontend HTTP request package",
5
5
  "license": "MIT",
6
6
  "homepage": "",
@@ -35,9 +35,9 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@babel/runtime": "^7.17.7",
38
- "@deppon/deppon-bridge": "2.4.23",
39
- "@deppon/deppon-ui": "2.4.23",
40
- "@deppon/deppon-utils": "2.4.23",
38
+ "@deppon/deppon-bridge": "2.4.24",
39
+ "@deppon/deppon-ui": "2.4.24",
40
+ "@deppon/deppon-utils": "2.4.24",
41
41
  "axios": "^0.26.0",
42
42
  "md5": "^2.3.0",
43
43
  "qs": "^6.10.3"