whistle.pastekitlab 1.3.1 → 1.3.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.
- package/back.js +107 -229
- package/index.js +10 -184
- package/package.json +1 -1
package/back.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Whistle Plugin for PasteKit Lab
|
|
3
|
-
*
|
|
4
|
-
* 功能:拦截匹配的域名请求,通过 WebSocket 发送到 Chrome 插件
|
|
2
|
+
* Whistle Plugin for PasteKit Lab(最终版 - 只监听)
|
|
5
3
|
*/
|
|
6
4
|
|
|
7
5
|
const WebSocket = require('ws');
|
|
8
|
-
const http = require('http');
|
|
9
6
|
const fs = require('fs');
|
|
10
7
|
const path = require('path');
|
|
11
8
|
|
|
@@ -13,297 +10,178 @@ const path = require('path');
|
|
|
13
10
|
const CONFIG = {
|
|
14
11
|
wsPort: 8889,
|
|
15
12
|
logEnabled: true,
|
|
16
|
-
logFile: path.join(__dirname, 'plugin.log')
|
|
13
|
+
logFile: path.join(__dirname, 'plugin.log')
|
|
17
14
|
};
|
|
18
15
|
|
|
19
16
|
// ==================== 全局状态 ====================
|
|
20
17
|
let wss = null;
|
|
21
|
-
let httpServer = null;
|
|
22
18
|
let clients = new Map();
|
|
23
19
|
let clientIdCounter = 0;
|
|
24
|
-
let domainConfig = [];
|
|
20
|
+
let domainConfig = [];
|
|
25
21
|
|
|
26
|
-
// ====================
|
|
22
|
+
// ==================== 日志 ====================
|
|
27
23
|
function log(message) {
|
|
28
|
-
if (CONFIG.logEnabled)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
} catch (e) {
|
|
39
|
-
// 忽略文件写入错误
|
|
40
|
-
}
|
|
41
|
-
}
|
|
24
|
+
if (!CONFIG.logEnabled) return;
|
|
25
|
+
|
|
26
|
+
const timestamp = new Date().toISOString();
|
|
27
|
+
const logMessage = `[${timestamp}] ${message}\n`;
|
|
28
|
+
|
|
29
|
+
console.log('[pastekitlab]', message);
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
fs.appendFileSync(CONFIG.logFile, logMessage, 'utf8');
|
|
33
|
+
} catch (e) {}
|
|
42
34
|
}
|
|
43
35
|
|
|
36
|
+
// ==================== 工具 ====================
|
|
44
37
|
function bufferToString(buffer) {
|
|
45
38
|
try {
|
|
46
39
|
if (!buffer) return null;
|
|
47
40
|
const result = buffer.toString('utf8');
|
|
48
|
-
if (/[^\x20-\x7E\r\n\t]/.test(result))
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
41
|
+
if (/[^\x20-\x7E\r\n\t]/.test(result)) return null;
|
|
51
42
|
return result;
|
|
52
|
-
} catch
|
|
43
|
+
} catch {
|
|
53
44
|
return null;
|
|
54
45
|
}
|
|
55
46
|
}
|
|
56
47
|
|
|
57
48
|
function bufferToBase64(buffer) {
|
|
58
49
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
} catch (e) {
|
|
50
|
+
return buffer ? buffer.toString('base64') : null;
|
|
51
|
+
} catch {
|
|
62
52
|
return null;
|
|
63
53
|
}
|
|
64
54
|
}
|
|
65
55
|
|
|
66
56
|
function generateId() {
|
|
67
|
-
return 'req_' + Date.now() + '_' + Math.random().toString(36).
|
|
57
|
+
return 'req_' + Date.now() + '_' + Math.random().toString(36).slice(2);
|
|
68
58
|
}
|
|
69
59
|
|
|
70
|
-
// ====================
|
|
60
|
+
// ==================== 域名过滤 ====================
|
|
71
61
|
function shouldIntercept(url) {
|
|
72
|
-
if (!domainConfig
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
62
|
+
if (!domainConfig.length) return true;
|
|
63
|
+
|
|
76
64
|
try {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
const { hostname } = new URL(url);
|
|
66
|
+
|
|
80
67
|
return domainConfig.some(domain => {
|
|
81
|
-
// 精确匹配
|
|
82
68
|
if (hostname === domain) return true;
|
|
83
|
-
// 通配符匹配 *.example.com
|
|
84
69
|
if (domain.startsWith('*.')) {
|
|
85
|
-
const
|
|
86
|
-
return hostname.endsWith('.' +
|
|
70
|
+
const base = domain.slice(2);
|
|
71
|
+
return hostname.endsWith('.' + base) || hostname === base;
|
|
87
72
|
}
|
|
88
73
|
return false;
|
|
89
74
|
});
|
|
90
|
-
} catch
|
|
75
|
+
} catch {
|
|
91
76
|
return false;
|
|
92
77
|
}
|
|
93
78
|
}
|
|
94
79
|
|
|
95
|
-
// ====================
|
|
80
|
+
// ==================== WebSocket ====================
|
|
96
81
|
function startWebSocketServer() {
|
|
97
82
|
if (wss) return;
|
|
98
83
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
maxPayload: 10 * 1024 * 1024
|
|
104
|
-
});
|
|
84
|
+
wss = new WebSocket.Server({
|
|
85
|
+
port: CONFIG.wsPort,
|
|
86
|
+
path: '/ws'
|
|
87
|
+
});
|
|
105
88
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const clientIp = req.socket.remoteAddress;
|
|
109
|
-
|
|
110
|
-
log(`客户端 ${clientId} 已连接 (${clientIp})`);
|
|
111
|
-
|
|
112
|
-
clients.set(clientId, {
|
|
113
|
-
id: clientId,
|
|
114
|
-
ws: ws,
|
|
115
|
-
ip: clientIp,
|
|
116
|
-
connectedAt: Date.now()
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// 发送欢迎消息
|
|
120
|
-
ws.send(JSON.stringify({
|
|
121
|
-
msgType: 'connected',
|
|
122
|
-
clientId: clientId,
|
|
123
|
-
timestamp: Date.now()
|
|
124
|
-
}));
|
|
125
|
-
|
|
126
|
-
// 设置心跳
|
|
127
|
-
ws.isAlive = true;
|
|
128
|
-
ws.on('pong', () => {
|
|
129
|
-
ws.isAlive = true;
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
// 处理客户端消息(接收 domain 配置)
|
|
133
|
-
ws.on('message', (data) => {
|
|
134
|
-
try {
|
|
135
|
-
const message = JSON.parse(data.toString());
|
|
136
|
-
|
|
137
|
-
if (message.msgType === 'domain') {
|
|
138
|
-
// 更新域名配置
|
|
139
|
-
domainConfig = message.domain || [];
|
|
140
|
-
log(`收到域名配置: ${domainConfig.length} 个域名`);
|
|
141
|
-
|
|
142
|
-
// 确认配置已接收
|
|
143
|
-
ws.send(JSON.stringify({
|
|
144
|
-
msgType: 'domainConfigReceived',
|
|
145
|
-
domainCount: domainConfig.length,
|
|
146
|
-
timestamp: Date.now()
|
|
147
|
-
}));
|
|
148
|
-
}
|
|
149
|
-
} catch (error) {
|
|
150
|
-
log(`消息解析失败: ${error.message}`);
|
|
151
|
-
}
|
|
152
|
-
});
|
|
89
|
+
wss.on('connection', (ws, req) => {
|
|
90
|
+
const id = ++clientIdCounter;
|
|
153
91
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
clients.delete(clientId);
|
|
157
|
-
});
|
|
92
|
+
clients.set(id, ws);
|
|
93
|
+
log(`客户端连接: ${id}`);
|
|
158
94
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
});
|
|
95
|
+
ws.send(JSON.stringify({
|
|
96
|
+
msgType: 'connected',
|
|
97
|
+
clientId: id
|
|
98
|
+
}));
|
|
164
99
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// if (ws.isAlive === false) {
|
|
169
|
-
// return ws.terminate();
|
|
170
|
-
// }
|
|
171
|
-
// ws.isAlive = false;
|
|
172
|
-
// ws.ping();
|
|
173
|
-
// });
|
|
174
|
-
// }, 30000);
|
|
175
|
-
|
|
176
|
-
wss.on('close', () => {
|
|
177
|
-
clearInterval(heartbeat);
|
|
178
|
-
});
|
|
100
|
+
ws.on('message', (data) => {
|
|
101
|
+
try {
|
|
102
|
+
const msg = JSON.parse(data.toString());
|
|
179
103
|
|
|
180
|
-
|
|
181
|
-
|
|
104
|
+
if (msg.msgType === 'domain') {
|
|
105
|
+
domainConfig = msg.domain || [];
|
|
106
|
+
log(`更新域名配置: ${domainConfig.join(',')}`);
|
|
107
|
+
}
|
|
108
|
+
} catch {}
|
|
182
109
|
});
|
|
183
110
|
|
|
184
|
-
|
|
111
|
+
ws.on('close', () => {
|
|
112
|
+
clients.delete(id);
|
|
113
|
+
log(`客户端断开: ${id}`);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
185
116
|
|
|
186
|
-
|
|
187
|
-
log(`启动 WebSocket 服务器失败: ${error.message}`);
|
|
188
|
-
}
|
|
117
|
+
log(`WebSocket 启动: ws://127.0.0.1:${CONFIG.wsPort}/ws`);
|
|
189
118
|
}
|
|
190
119
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (clients.size === 0) return;
|
|
120
|
+
function broadcast(type, data) {
|
|
121
|
+
if (!clients.size) return;
|
|
194
122
|
|
|
195
|
-
const
|
|
196
|
-
msgType:
|
|
123
|
+
const msg = JSON.stringify({
|
|
124
|
+
msgType: type,
|
|
197
125
|
...data,
|
|
198
126
|
timestamp: Date.now()
|
|
199
127
|
});
|
|
200
128
|
|
|
201
|
-
clients.forEach(
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
client.ws.send(message);
|
|
205
|
-
} catch (error) {
|
|
206
|
-
log(`向客户端 ${clientId} 发送失败`);
|
|
207
|
-
}
|
|
129
|
+
clients.forEach(ws => {
|
|
130
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
131
|
+
ws.send(msg);
|
|
208
132
|
}
|
|
209
133
|
});
|
|
210
134
|
}
|
|
211
135
|
|
|
212
|
-
// ==================== Whistle
|
|
213
|
-
module.exports = {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
*/
|
|
217
|
-
'*': async function(req, res, next) {
|
|
218
|
-
// 确保 WebSocket 服务器已启动
|
|
219
|
-
if (!wss) {
|
|
220
|
-
startWebSocketServer();
|
|
221
|
-
}
|
|
136
|
+
// ==================== Whistle 插件 ====================
|
|
137
|
+
module.exports = (server, options) => {
|
|
138
|
+
log('插件已启动(server.on 模式)');
|
|
139
|
+
startWebSocketServer();
|
|
222
140
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
// return next();
|
|
229
|
-
// }
|
|
230
|
-
|
|
231
|
-
const method = req.method;
|
|
232
|
-
const headers = req.headers;
|
|
141
|
+
// ==================== 请求监听 ====================
|
|
142
|
+
server.on('request', (req, res) => {
|
|
143
|
+
try {
|
|
144
|
+
const url = req.fullUrl || req.url;
|
|
145
|
+
if (!shouldIntercept(url)) return;
|
|
233
146
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
147
|
+
const data = {
|
|
148
|
+
eventId: generateId(),
|
|
149
|
+
url,
|
|
150
|
+
method: req.method,
|
|
151
|
+
headers: req.headers,
|
|
152
|
+
body: bufferToString(req._reqBody),
|
|
153
|
+
bodyBase64: bufferToBase64(req._reqBody)
|
|
154
|
+
};
|
|
237
155
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
requestBodyBase64 = bufferToBase64(req._reqBody);
|
|
241
|
-
}
|
|
156
|
+
log(`REQ ${req.method} ${url}`);
|
|
157
|
+
broadcast('REQUEST', data);
|
|
242
158
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
eventId: generateId(),
|
|
246
|
-
url: url,
|
|
247
|
-
method: method,
|
|
248
|
-
requestHeaders: headers,
|
|
249
|
-
requestBody: requestBody,
|
|
250
|
-
requestBodyBase64: requestBodyBase64,
|
|
251
|
-
timestamp: Date.now()
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
log(`拦截请求: ${method} ${url}`);
|
|
255
|
-
|
|
256
|
-
// 发送请求数据给 Chrome 插件
|
|
257
|
-
broadcastToClients('MOCK', requestData);
|
|
258
|
-
|
|
259
|
-
next();
|
|
260
|
-
},
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* 处理响应阶段 - afterResponse
|
|
264
|
-
*/
|
|
265
|
-
'* response': async function(req, res, next) {
|
|
266
|
-
const url = req.fullUrl || req.url;
|
|
267
|
-
log(`接收到响应${req}`)
|
|
268
|
-
|
|
269
|
-
// // 检查是否匹配配置的域名
|
|
270
|
-
// if (!shouldIntercept(url)) {
|
|
271
|
-
// return next();
|
|
272
|
-
// }
|
|
273
|
-
|
|
274
|
-
const statusCode = res.statusCode;
|
|
275
|
-
const headers = res.headers;
|
|
276
|
-
|
|
277
|
-
// 获取响应体
|
|
278
|
-
let responseBody = null;
|
|
279
|
-
let responseBodyBase64 = null;
|
|
280
|
-
|
|
281
|
-
if (res._resBody) {
|
|
282
|
-
responseBody = bufferToString(res._resBody);
|
|
283
|
-
responseBodyBase64 = bufferToBase64(res._resBody);
|
|
159
|
+
} catch (e) {
|
|
160
|
+
log('request error: ' + e.message);
|
|
284
161
|
}
|
|
162
|
+
});
|
|
285
163
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
url
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
};
|
|
164
|
+
// ==================== 响应监听 ====================
|
|
165
|
+
server.on('response', (req, res) => {
|
|
166
|
+
try {
|
|
167
|
+
const url = req.fullUrl || req.url;
|
|
168
|
+
if (!shouldIntercept(url)) return;
|
|
169
|
+
|
|
170
|
+
const data = {
|
|
171
|
+
eventId: generateId(),
|
|
172
|
+
url,
|
|
173
|
+
method: req.method,
|
|
174
|
+
statusCode: res.statusCode,
|
|
175
|
+
headers: res.headers,
|
|
176
|
+
body: bufferToString(res._resBody),
|
|
177
|
+
bodyBase64: bufferToBase64(res._resBody)
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
log(`RES ${res.statusCode} ${url}`);
|
|
181
|
+
broadcast('RESPONSE', data);
|
|
306
182
|
|
|
307
|
-
|
|
308
|
-
log('
|
|
309
|
-
|
|
183
|
+
} catch (e) {
|
|
184
|
+
log('response error: ' + e.message);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
};
|
package/index.js
CHANGED
|
@@ -1,187 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Whistle Plugin for PasteKit Lab(最终版 - 只监听)
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const WebSocket = require('ws');
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
|
|
9
|
-
// ==================== 配置 ====================
|
|
10
|
-
const CONFIG = {
|
|
11
|
-
wsPort: 8889,
|
|
12
|
-
logEnabled: true,
|
|
13
|
-
logFile: path.join(__dirname, 'plugin.log')
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
// ==================== 全局状态 ====================
|
|
17
|
-
let wss = null;
|
|
18
|
-
let clients = new Map();
|
|
19
|
-
let clientIdCounter = 0;
|
|
20
|
-
let domainConfig = [];
|
|
21
|
-
|
|
22
|
-
// ==================== 日志 ====================
|
|
23
|
-
function log(message) {
|
|
24
|
-
if (!CONFIG.logEnabled) return;
|
|
25
|
-
|
|
26
|
-
const timestamp = new Date().toISOString();
|
|
27
|
-
const logMessage = `[${timestamp}] ${message}\n`;
|
|
28
|
-
|
|
29
|
-
console.log('[pastekitlab]', message);
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
fs.appendFileSync(CONFIG.logFile, logMessage, 'utf8');
|
|
33
|
-
} catch (e) {}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// ==================== 工具 ====================
|
|
37
|
-
function bufferToString(buffer) {
|
|
38
|
-
try {
|
|
39
|
-
if (!buffer) return null;
|
|
40
|
-
const result = buffer.toString('utf8');
|
|
41
|
-
if (/[^\x20-\x7E\r\n\t]/.test(result)) return null;
|
|
42
|
-
return result;
|
|
43
|
-
} catch {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function bufferToBase64(buffer) {
|
|
49
|
-
try {
|
|
50
|
-
return buffer ? buffer.toString('base64') : null;
|
|
51
|
-
} catch {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function generateId() {
|
|
57
|
-
return 'req_' + Date.now() + '_' + Math.random().toString(36).slice(2);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ==================== 域名过滤 ====================
|
|
61
|
-
function shouldIntercept(url) {
|
|
62
|
-
if (!domainConfig.length) return true;
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
const { hostname } = new URL(url);
|
|
66
|
-
|
|
67
|
-
return domainConfig.some(domain => {
|
|
68
|
-
if (hostname === domain) return true;
|
|
69
|
-
if (domain.startsWith('*.')) {
|
|
70
|
-
const base = domain.slice(2);
|
|
71
|
-
return hostname.endsWith('.' + base) || hostname === base;
|
|
72
|
-
}
|
|
73
|
-
return false;
|
|
74
|
-
});
|
|
75
|
-
} catch {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ==================== WebSocket ====================
|
|
81
|
-
function startWebSocketServer() {
|
|
82
|
-
if (wss) return;
|
|
83
|
-
|
|
84
|
-
wss = new WebSocket.Server({
|
|
85
|
-
port: CONFIG.wsPort,
|
|
86
|
-
path: '/ws'
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
wss.on('connection', (ws, req) => {
|
|
90
|
-
const id = ++clientIdCounter;
|
|
91
|
-
|
|
92
|
-
clients.set(id, ws);
|
|
93
|
-
log(`客户端连接: ${id}`);
|
|
94
|
-
|
|
95
|
-
ws.send(JSON.stringify({
|
|
96
|
-
msgType: 'connected',
|
|
97
|
-
clientId: id
|
|
98
|
-
}));
|
|
99
|
-
|
|
100
|
-
ws.on('message', (data) => {
|
|
101
|
-
try {
|
|
102
|
-
const msg = JSON.parse(data.toString());
|
|
103
|
-
|
|
104
|
-
if (msg.msgType === 'domain') {
|
|
105
|
-
domainConfig = msg.domain || [];
|
|
106
|
-
log(`更新域名配置: ${domainConfig.join(',')}`);
|
|
107
|
-
}
|
|
108
|
-
} catch {}
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
ws.on('close', () => {
|
|
112
|
-
clients.delete(id);
|
|
113
|
-
log(`客户端断开: ${id}`);
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
log(`WebSocket 启动: ws://127.0.0.1:${CONFIG.wsPort}/ws`);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function broadcast(type, data) {
|
|
121
|
-
if (!clients.size) return;
|
|
122
|
-
|
|
123
|
-
const msg = JSON.stringify({
|
|
124
|
-
msgType: type,
|
|
125
|
-
...data,
|
|
126
|
-
timestamp: Date.now()
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
clients.forEach(ws => {
|
|
130
|
-
if (ws.readyState === WebSocket.OPEN) {
|
|
131
|
-
ws.send(msg);
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ==================== Whistle 插件 ====================
|
|
137
1
|
module.exports = (server, options) => {
|
|
138
|
-
log('
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const data = {
|
|
148
|
-
eventId: generateId(),
|
|
149
|
-
url,
|
|
150
|
-
method: req.method,
|
|
151
|
-
headers: req.headers,
|
|
152
|
-
body: bufferToString(req._reqBody),
|
|
153
|
-
bodyBase64: bufferToBase64(req._reqBody)
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
log(`REQ ${req.method} ${url}`);
|
|
157
|
-
broadcast('REQUEST', data);
|
|
158
|
-
|
|
159
|
-
} catch (e) {
|
|
160
|
-
log('request error: ' + e.message);
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
// ==================== 响应监听 ====================
|
|
165
|
-
server.on('response', (req, res) => {
|
|
166
|
-
try {
|
|
167
|
-
const url = req.fullUrl || req.url;
|
|
168
|
-
if (!shouldIntercept(url)) return;
|
|
169
|
-
|
|
170
|
-
const data = {
|
|
171
|
-
eventId: generateId(),
|
|
172
|
-
url,
|
|
173
|
-
method: req.method,
|
|
174
|
-
statusCode: res.statusCode,
|
|
175
|
-
headers: res.headers,
|
|
176
|
-
body: bufferToString(res._resBody),
|
|
177
|
-
bodyBase64: bufferToBase64(res._resBody)
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
log(`RES ${res.statusCode} ${url}`);
|
|
181
|
-
broadcast('RESPONSE', data);
|
|
182
|
-
|
|
183
|
-
} catch (e) {
|
|
184
|
-
log('response error: ' + e.message);
|
|
2
|
+
console.log('>>> plugin loaded');
|
|
3
|
+
// server.on('request', (req, res) => {
|
|
4
|
+
// console.log('>>> takeover:', req.fullUrl);
|
|
5
|
+
// // 直接用
|
|
6
|
+
// });
|
|
7
|
+
return {
|
|
8
|
+
request: (req, res,next) => {
|
|
9
|
+
console.log('>>> takeover:', req.fullUrl);
|
|
10
|
+
return next();
|
|
185
11
|
}
|
|
186
|
-
}
|
|
12
|
+
};
|
|
187
13
|
};
|
package/package.json
CHANGED