@mauribadnights/clooks 0.6.1 → 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 +14 -9
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -91,7 +91,12 @@ function readBody(req) {
|
|
|
91
91
|
}
|
|
92
92
|
function sendJson(res, status, data) {
|
|
93
93
|
const body = JSON.stringify(data);
|
|
94
|
-
|
|
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
|
+
}
|
|
95
100
|
try {
|
|
96
101
|
res.writeHead(status, {
|
|
97
102
|
'Content-Type': 'application/json',
|
|
@@ -159,14 +164,7 @@ function createServer(manifest, metrics) {
|
|
|
159
164
|
const source = req.socket.remoteAddress ?? 'unknown';
|
|
160
165
|
// Rate limiting: check if this source has too many auth failures
|
|
161
166
|
if (!rateLimiter.check(source)) {
|
|
162
|
-
|
|
163
|
-
const body = JSON.stringify({ error: 'Too many auth failures' });
|
|
164
|
-
res.writeHead(429, {
|
|
165
|
-
'Content-Type': 'application/json',
|
|
166
|
-
'Content-Length': Buffer.byteLength(body),
|
|
167
|
-
'Retry-After': String(retryAfter),
|
|
168
|
-
});
|
|
169
|
-
res.end(body);
|
|
167
|
+
sendJson(res, 429, { error: 'Too many auth failures' });
|
|
170
168
|
return;
|
|
171
169
|
}
|
|
172
170
|
const authHeader = req.headers['authorization'];
|
|
@@ -317,6 +315,13 @@ function startDaemon(manifest, metrics, options) {
|
|
|
317
315
|
return new Promise((resolve, reject) => {
|
|
318
316
|
const ctx = createServer(manifest, metrics);
|
|
319
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
|
+
});
|
|
320
325
|
ctx.server.on('error', async (err) => {
|
|
321
326
|
if (err.code === 'EADDRINUSE') {
|
|
322
327
|
log(`Port ${port} already in use — attempting orphan recovery`);
|
package/package.json
CHANGED