Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I wrap every express js request in a domain or trycatch

Is it possible to wrap every request coming through express.js in a domain or trycatch see trycatch info here?

I am trying to create a 'catch all' of sorts (the express error handler middleware does not catch async calls) to be sure any errors I miss are handled with a 500 being sent to the user.

If you have an asynchronous function call (eg. process.nextTick()), then it will be outside the scope of express' error handler, thus killing the process entirely. Thus, using the express error handler will not work in all cases.

like image 742
Ben Zuill-Smith Avatar asked Oct 30 '13 18:10

Ben Zuill-Smith


People also ask

Which method is used to send the content in Express js?

send() function basically sends the HTTP response. The body parameter can be a String or a Buffer object or an object or an Array.

Is Express js unmaintained?

It is unmaintained Express has not been updated for years, and its next version has been in alpha for 6 years. People may think it is not updated because the API is stable and does not need change. The reality is: Express does not know how to handle async/await .

What is get method in Express js?

get()` Function in Express. Express' app. get() function lets you define a route handler for GET requests to a given URL. For example, the below code registers a route handler that Express will call when it receives an HTTP GET request to /test .


1 Answers

Express already has error handler implementation. It inherit it from connect. To use it you need to add it as the last middleware point (last app.use(...) call). For example:

var express = require('express')
  , app = express();

app.use(app.router);
app.use(express.errorHandler());

// app.get(...), app.post(...), app.listen(...), etc.

If you want to handle all errors with simple 500 response code, you could replace express.errorHandler() with you own function. In that case your code will looks like:

var express = require('express')
  , app = express();

app.use(app.router);
app.use(function(err, req, res, next){
  if (!err) return next();
  res.send(500);
});

// app.get(...), app.post(...), app.listen(...), etc.

More information about that way could be found in express error example comments in code

UPDATE:

Of course you could use domain for each request. You could wrap each request separately or use wrapping for router to handle ALL exceptions. Code is following:

var express = require('express')
    , http = require('http')
    , app = express()
    , domain = require('domain');

//app.use(app.router);
app.use(function(req, res, next){
    var d = domain.create();
    d.on('error', function(er) {
        console.log('error, but oh well', er.message);
        res.send(500);
    });

    // explicitly add req and res
    d.add(req);
    d.add(res);

    d.run(function() {
        app.router(req, res, next);
    });
});

app.get('/', function(req,res){
    process.nextTick(function(){
        throw new Error('Check Error');
    });
});

http.createServer(app).listen(3000, function(){
    console.log('Express server listening on port 3000');
});

!!BUT!! never use this in production. The reason of that is in nature how JS throw work. It will definitely be a cause of leaking in your application and make it even more unstable. You could use such error handling to implement custom algorithm of shutdown (for example to close already opened connection). More information about right use of domain could be found in documentation.

To monitor the leaking you could use the technique from this article.

UPDATE 2:

I just can't leave this not finished. trycatch code:

var express = require('express')
    , http = require('http')
    , app = express()
    , domain = require('domain')
    , trycatch = require('trycatch');

//app.use(app.router);
app.use(function(req, res, next){
   trycatch(function(){
           app.router(req, res, next);
       }, function(er){
           console.log(er.message);
           res.send(500);
       });
});

app.get('/', function(req,res){
    process.nextTick(function(){
        throw new Error('Check Error');
    });
});

http.createServer(app).listen(3000, function(){
    console.log('Express server listening on port 3000');
});

I had review the source of trycatch and there was no any magic. It still be cause of leaks. trycatch has domain under the hood.

like image 130
andbas Avatar answered Oct 18 '22 03:10

andbas