whistle.mockbubu 2.2.0-beta.2 → 2.2.0-beta.3
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.
|
@@ -78,6 +78,12 @@ async function captureResponse(params) {
|
|
|
78
78
|
return
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
const resContentType = svrRes.headers['content-type'] || ''
|
|
82
|
+
if (!resContentType.includes('application/json')) {
|
|
83
|
+
console.log(`[mockbubu] ⏭️ 非 JSON 响应,跳过捕获: ${filename} (Content-Type: ${resContentType})`)
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
console.log(`[mockbubu 2025/12/8 ${new Date().toLocaleTimeString()}] 📦 响应接收完成,开始解压: ${filename}`)
|
|
82
88
|
// 解压响应体
|
|
83
89
|
const content = await handleBuffer2String({ body, encoding })
|
package/lib/utils/utils.js
CHANGED
|
@@ -370,6 +370,7 @@ const getRule = (originalReq) => {
|
|
|
370
370
|
const isJsonReq = (headers) => {
|
|
371
371
|
const result = (
|
|
372
372
|
(headers.accept && headers.accept.includes('application/json')) ||
|
|
373
|
+
headers.accept === '*/*' ||
|
|
373
374
|
headers['sec-fetch-dest'] === 'empty' ||
|
|
374
375
|
headers['Sec-Fetch-Dest'] === 'empty'
|
|
375
376
|
)
|
package/package.json
CHANGED
package/public/js/app.js
CHANGED
|
@@ -243,6 +243,36 @@ const __default__ = {
|
|
|
243
243
|
|
|
244
244
|
// 是否已加载已保存文件
|
|
245
245
|
let savedFilesLoaded = false;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* 从 session 中提取 URL 查询参数
|
|
249
|
+
*
|
|
250
|
+
* x-whistle-full-url 是 Whistle 内部 header,只在 originalReq 阶段可靠。
|
|
251
|
+
* getSession() 返回的 session.req.headers 可能已被剥离该字段,
|
|
252
|
+
* 因此先尝试 x-whistle-full-url,不存在时 fallback 到 session.url(Whistle session 顶层字段,含完整 query string)。
|
|
253
|
+
*/
|
|
254
|
+
const extractQueryFromSession = session => {
|
|
255
|
+
const fullUrlEncoded = session?.req?.headers?.['x-whistle-full-url'];
|
|
256
|
+
if (fullUrlEncoded) {
|
|
257
|
+
try {
|
|
258
|
+
const urlObj = new URL(decodeURIComponent(fullUrlEncoded));
|
|
259
|
+
return Object.fromEntries(urlObj.searchParams);
|
|
260
|
+
} catch (e) {
|
|
261
|
+
// 解析失败,继续 fallback
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Whistle session 顶层 url 字段包含完整 URL(含 query string)
|
|
265
|
+
const reqUrl = session?.url;
|
|
266
|
+
if (reqUrl) {
|
|
267
|
+
try {
|
|
268
|
+
const urlObj = new URL(reqUrl);
|
|
269
|
+
return Object.fromEntries(urlObj.searchParams);
|
|
270
|
+
} catch (e) {
|
|
271
|
+
// 解析失败,返回空对象
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return {};
|
|
275
|
+
};
|
|
246
276
|
const getRules = rules => {
|
|
247
277
|
const {
|
|
248
278
|
defaultRules,
|
|
@@ -384,17 +414,7 @@ const __default__ = {
|
|
|
384
414
|
// 映射未保存数据的展示字段
|
|
385
415
|
const newCachedItems = filteredData.map(item => {
|
|
386
416
|
// 从 session 中提取 URL 查询参数
|
|
387
|
-
|
|
388
|
-
const fullUrlEncoded = item.session?.req?.headers?.['x-whistle-full-url'];
|
|
389
|
-
if (fullUrlEncoded) {
|
|
390
|
-
try {
|
|
391
|
-
const fullUrl = decodeURIComponent(fullUrlEncoded);
|
|
392
|
-
const urlObj = new URL(fullUrl);
|
|
393
|
-
query = Object.fromEntries(urlObj.searchParams);
|
|
394
|
-
} catch (e) {
|
|
395
|
-
// 静默处理URL解析错误
|
|
396
|
-
}
|
|
397
|
-
}
|
|
417
|
+
const query = extractQueryFromSession(item.session);
|
|
398
418
|
|
|
399
419
|
// 从 session 中提取 payload (请求体)
|
|
400
420
|
const payload = item.session?.req?.body || null;
|
|
@@ -515,17 +535,7 @@ const __default__ = {
|
|
|
515
535
|
}
|
|
516
536
|
|
|
517
537
|
// 从 session 提取 query 参数
|
|
518
|
-
|
|
519
|
-
const fullUrlEncoded = data.session?.req?.headers?.['x-whistle-full-url'];
|
|
520
|
-
if (fullUrlEncoded) {
|
|
521
|
-
try {
|
|
522
|
-
const fullUrl = decodeURIComponent(fullUrlEncoded);
|
|
523
|
-
const urlObj = new URL(fullUrl);
|
|
524
|
-
query = Object.fromEntries(urlObj.searchParams);
|
|
525
|
-
} catch (e) {
|
|
526
|
-
// 静默处理URL解析错误
|
|
527
|
-
}
|
|
528
|
-
}
|
|
538
|
+
const query = extractQueryFromSession(data.session);
|
|
529
539
|
|
|
530
540
|
// 使用 Object.assign 更新 currentRow,保留引用
|
|
531
541
|
Object.assign(currentRow.value, {
|
|
@@ -1271,12 +1281,13 @@ const __default__ = {
|
|
|
1271
1281
|
}
|
|
1272
1282
|
};
|
|
1273
1283
|
(0,vue__WEBPACK_IMPORTED_MODULE_21__.watch)(currentRow, val => {
|
|
1274
|
-
// 只对已保存的文件调用 getCurrentRowData
|
|
1275
|
-
// 未保存的缓存数据已经包含完整 session,不需要再次获取
|
|
1276
|
-
// 判断依据: 有 id 字段说明是已保存的文件,需要按需加载完整数据
|
|
1277
1284
|
if (val && val.id) {
|
|
1278
|
-
//
|
|
1285
|
+
// 已保存文件:按需加载完整数据(含 query/payload/headers)
|
|
1279
1286
|
getCurrentRowData(val);
|
|
1287
|
+
} else if (val && val.session) {
|
|
1288
|
+
// 缓存数据:session 已在轮询时附带,但 query 可能在旧版本代码下提取失败
|
|
1289
|
+
// 切换行时重新提取,确保展示正确
|
|
1290
|
+
val.query = extractQueryFromSession(val.session);
|
|
1280
1291
|
}
|
|
1281
1292
|
});
|
|
1282
1293
|
(0,vue__WEBPACK_IMPORTED_MODULE_21__.onMounted)(async () => {
|
|
@@ -1335,6 +1346,7 @@ const __default__ = {
|
|
|
1335
1346
|
pollingStartTime,
|
|
1336
1347
|
intervalId,
|
|
1337
1348
|
savedFilesLoaded,
|
|
1349
|
+
extractQueryFromSession,
|
|
1338
1350
|
getRules,
|
|
1339
1351
|
getInit,
|
|
1340
1352
|
pageShow,
|