@mauribadnights/clooks 0.6.0 → 0.6.2
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/dist/server.js +22 -13
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -91,11 +91,20 @@ function readBody(req) {
|
|
|
91
91
|
}
|
|
92
92
|
function sendJson(res, status, data) {
|
|
93
93
|
const body = JSON.stringify(data);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
// Guard against EPIPE: add listener only once per socket (keep-alive sockets are reused
|
|
95
|
+
// across requests — adding a listener per-request accumulates them and triggers
|
|
96
|
+
// MaxListenersExceededWarning after ~10 requests on the same connection).
|
|
97
|
+
if (res.socket && res.socket.listenerCount('error') === 0) {
|
|
98
|
+
res.socket.on('error', () => { }); // suppress EPIPE if client disconnected
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
res.writeHead(status, {
|
|
102
|
+
'Content-Type': 'application/json',
|
|
103
|
+
'Content-Length': Buffer.byteLength(body),
|
|
104
|
+
});
|
|
105
|
+
res.end(body);
|
|
106
|
+
}
|
|
107
|
+
catch (_) { }
|
|
99
108
|
}
|
|
100
109
|
/**
|
|
101
110
|
* Create the HTTP server for hook handling.
|
|
@@ -155,14 +164,7 @@ function createServer(manifest, metrics) {
|
|
|
155
164
|
const source = req.socket.remoteAddress ?? 'unknown';
|
|
156
165
|
// Rate limiting: check if this source has too many auth failures
|
|
157
166
|
if (!rateLimiter.check(source)) {
|
|
158
|
-
|
|
159
|
-
const body = JSON.stringify({ error: 'Too many auth failures' });
|
|
160
|
-
res.writeHead(429, {
|
|
161
|
-
'Content-Type': 'application/json',
|
|
162
|
-
'Content-Length': Buffer.byteLength(body),
|
|
163
|
-
'Retry-After': String(retryAfter),
|
|
164
|
-
});
|
|
165
|
-
res.end(body);
|
|
167
|
+
sendJson(res, 429, { error: 'Too many auth failures' });
|
|
166
168
|
return;
|
|
167
169
|
}
|
|
168
170
|
const authHeader = req.headers['authorization'];
|
|
@@ -313,6 +315,13 @@ function startDaemon(manifest, metrics, options) {
|
|
|
313
315
|
return new Promise((resolve, reject) => {
|
|
314
316
|
const ctx = createServer(manifest, metrics);
|
|
315
317
|
const port = manifest.settings?.port ?? constants_js_1.DEFAULT_PORT;
|
|
318
|
+
// Catch EPIPE at connection birth — handles the window between request arrival
|
|
319
|
+
// and the first sendJson call (e.g., during slow async handler execution).
|
|
320
|
+
// Without this, an EPIPE that arrives before sendJson's per-response listener
|
|
321
|
+
// is attached becomes an unhandled error event and crashes the process.
|
|
322
|
+
ctx.server.on('connection', (socket) => {
|
|
323
|
+
socket.on('error', () => { }); // no-op: client disconnected mid-flight
|
|
324
|
+
});
|
|
316
325
|
ctx.server.on('error', async (err) => {
|
|
317
326
|
if (err.code === 'EADDRINUSE') {
|
|
318
327
|
log(`Port ${port} already in use — attempting orphan recovery`);
|
package/package.json
CHANGED