Skip to content

Unable to Execute Asynchronous Code (Both Promises and Callbacks) in Middleware #1982

@vishalkumar14

Description

@vishalkumar14

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)

Image

Can anyone please help me with the issue?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions