-
Notifications
You must be signed in to change notification settings - Fork 983
Description
Bug Report
I thoroughly searched the existing issues in the Restify repository to check if this problem had already been reported. However, I could not find any issue that matches the exact behavior I am experiencing. While there are some discussions around bodyParser, none of them address the specific problem where the request connection is prematurely marked as closed when handling POST requests
Restify Version
v5.0.0 (also tested on latest version as well)
Node.js Version
v22.11.0 ( also tested with 16.19.0)
OS
Ubuntu 20.04 (WSL2), Windows 11
Expected behaviour
Middleware should proceed sequentially to the next handler when next() is called.
Actual behaviour
When using restify.plugins.bodyParser(), the request connection state is unexpectedly marked as closed. If a middleware function performs an async operation (e.g., setTimeout, async/await), calling next() after the delay results in a RequestCloseError.
This issue only occurs for POST requests.
Code
`
const restify = require('restify');
const server = restify.createServer({ handleUncaughtExceptions: true });
server.pre(function (req, res, next) {
restify.pre.userAgentConnection();
req.start = Date.now();
req.requestId = req.header('X-Request-Id') || req.getId();
return next();
});
server.use(restify.plugins.acceptParser(server.acceptable));
server.use(restify.plugins.authorizationParser());
server.use(restify.plugins.dateParser());
server.use(restify.plugins.queryParser());
server.use(restify.plugins.bodyParser({ mapParams: false }));
server.on('uncaughtException', function (req, res, route, err) {
res.send(500, { code: 'UNKNOWN', message: 'UNKNOWN' });
});
server.on('after', function (req, res, route, error) {
console.log("server after event :: ", error)
});
process.on('exit', function () {
console.log(`Stopped server `);
});
function connectionStateCheck(req, res, next) {
const connection = req.connection;
req.on('close', () => {
console.log(`Connection closed for ${req.url}`);
});
req.on('end', () => {
console.log(`Connection end for ${req.url}`);
});
connection.on('close', () => {
console.log(`Connection closed for ${req.url}`);
});
connection.on('end', () => {
console.log(`Connection ended for ${req.url}`);
});
next();
}
server.use(connectionStateCheck);
function helperMiddleware() {
return function hh(req, res, next) {
console.log("Middleware started");
setTimeout(() => {
console.log("Async operation completed, calling next()");
req.authdata = {};
return next();
}, 3000);
console.log("Middleware function execution ends");
}
}
server.get('/', (req, res, next) => {
console.log("Final handler executed");
res.send("Hello, world!");
next();
});
server.use(helperMiddleware());
server.get('/test', (req, res, next) => {
console.log("test handler executed");
res.send("test, world!");
next();
});
server.post('/testpost', (req, res, next) => {
console.log("testpost handler executed :: ", req.body);
res.send("test, world!");
next();
});
server.listen(8080, () => {
console.log("Server listening on port 8080");
});
`
What's Happening
- Everything works fine until the request hits bodyParser.
- bodyParser executes successfully and passes control to the next middleware (helperMiddleware).
- The next middleware (helperMiddleware) runs synchronously until it reaches setTimeout().
- Before setTimeout() executes, Restify marks the request connection as closed.
- Calling next() after the async operation throws RequestCloseError.
- Removing bodyParser or helperMiddleware fixes the issue but i need both the middleware
- Only affects POST requests (GET requests work fine)
Can anyone please help me with the issue?