@skrillex1224/playwright-toolkit 3.0.7 → 3.0.9

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.
@@ -32,6 +32,25 @@ const state = {
32
32
  : null,
33
33
  };
34
34
 
35
+ const formatFatalError = (error) => {
36
+ if (error instanceof Error) {
37
+ return error.stack || error.message || String(error);
38
+ }
39
+ try {
40
+ return JSON.stringify(error);
41
+ } catch {
42
+ return String(error);
43
+ }
44
+ };
45
+
46
+ const exitAfterFatal = (kind, error) => {
47
+ try {
48
+ console.error(`[proxy-meter] fatal ${kind}: ${formatFatalError(error)}`);
49
+ } catch {}
50
+ flushSnapshot();
51
+ process.exit(1);
52
+ };
53
+
35
54
  const getHostBucket = (host) => {
36
55
  if (!host) return null;
37
56
  if (!state.hosts[host]) {
@@ -60,6 +79,21 @@ const safeError = (error) => {
60
79
  return message.length > 240 ? message.slice(0, 240) : message;
61
80
  };
62
81
 
82
+ const sendBadGateway = (res, error = null) => {
83
+ if (!res || res.destroyed || res.writableEnded) return;
84
+
85
+ try {
86
+ if (!res.headersSent) {
87
+ res.writeHead(502);
88
+ res.end('Bad Gateway');
89
+ return;
90
+ }
91
+
92
+ // Headers are already committed; the only truthful error signal left is closing the stream.
93
+ res.destroy(error instanceof Error ? error : undefined);
94
+ } catch {}
95
+ };
96
+
63
97
  const statusLabel = (statusCode, error) => {
64
98
  const code = Number(statusCode) || 0;
65
99
  if (error || code <= 0) return 'ERR';
@@ -349,8 +383,7 @@ const forwardHttp = (req, res) => {
349
383
 
350
384
  if (!target) {
351
385
  tracker.close({ statusCode: 0, error: 'invalid_target_url' });
352
- res.writeHead(502);
353
- res.end('Bad Gateway');
386
+ sendBadGateway(res);
354
387
  return;
355
388
  }
356
389
 
@@ -381,7 +414,19 @@ const forwardHttp = (req, res) => {
381
414
  let responseStatus = 0;
382
415
  const proxyReq = http.request(requestOptions, (proxyRes) => {
383
416
  responseStatus = Number(proxyRes.statusCode) || 0;
384
- res.writeHead(responseStatus || 502, proxyRes.headers);
417
+ if (res.destroyed || res.writableEnded) {
418
+ tracker.close({ statusCode: responseStatus || 499, error: 'client_response_closed' });
419
+ proxyRes.resume();
420
+ return;
421
+ }
422
+ try {
423
+ res.writeHead(responseStatus || 502, proxyRes.headers);
424
+ } catch (error) {
425
+ tracker.close({ statusCode: responseStatus, error: safeError(error) });
426
+ proxyRes.resume();
427
+ sendBadGateway(res, error);
428
+ return;
429
+ }
385
430
  proxyRes.on('data', (chunk) => {
386
431
  const size = chunk?.length || 0;
387
432
  addTraffic(hostname, 'in', size);
@@ -412,8 +457,7 @@ const forwardHttp = (req, res) => {
412
457
 
413
458
  proxyReq.on('error', (error) => {
414
459
  tracker.close({ statusCode: responseStatus, error: safeError(error) });
415
- res.writeHead(502);
416
- res.end('Bad Gateway');
460
+ sendBadGateway(res, error);
417
461
  });
418
462
  };
419
463
 
@@ -545,5 +589,7 @@ const shutdown = () => {
545
589
  process.exit(0);
546
590
  };
547
591
 
592
+ process.on('uncaughtException', (error) => exitAfterFatal('uncaughtException', error));
593
+ process.on('unhandledRejection', (error) => exitAfterFatal('unhandledRejection', error));
548
594
  process.on('SIGINT', shutdown);
549
595
  process.on('SIGTERM', shutdown);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skrillex1224/playwright-toolkit",
3
- "version": "3.0.7",
3
+ "version": "3.0.9",
4
4
  "description": "一个在 Apify/Crawlee Actor 中启用实时截图视图的实用工具库。",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",