Tim Sawyer
Tim Sawyer

Reputation: 15

Node.js Express Middleware Error Chain

I have to scrape a web page for a key to use later as a cookie. That part works. But because the request is async the error is not handled. I want to make sure the error is passed along the middleware chain. But I can't get my brain around this one. Thanks for helping.

app.use('/', makeLoginCookie, function (req, res, next){
    console.log('My app.use() starts here.');
    //console.log('makeLoginCookie: %s', err);
    next(); 
});

And here's the function

function makeLoginCookie(req, res, next) {
    httpOptions = {
        url: site.url,
        headers: {
            Cookie: null
        }
    }

// Get HIDDEN key, build login cookie
request(httpOptions, function(error, response, body) {
    if (!error && response.statusCode == 200) {
        //console.log(body)
        var match = body.match( /\<INPUT TYPE=HIDDEN id=\"key\", value=\"([0-9a-f]+)\"\>/i );
        var key = match[1]
        var encrypted = sha1(key + site.username + site.password);
        loginCookie = "username=" + key + ";password=" + encrypted;
        next();
    } else {
        console.log("Connect failed %s" , error);
        //err = new Error("Can't connect");
        next();
    }
  });
};

Upvotes: 1

Views: 1047

Answers (3)

Tim Sawyer
Tim Sawyer

Reputation: 15

There must have been some error elsewhere in my code because this works as expected now.

} else {
    console.log("Connect failed %s" , error);
    err = new Error("Can't connect");
    next(err);
}

Upvotes: 0

Renan Caldas
Renan Caldas

Reputation: 56

I would use promises (Q library) in order to resolve this, and for another things too, specially for web scraping. Your "makeLoginCookie" function could return a deferred.promise and, when the request fails, reject it with the error.

Edit 1: I recommend this great video that explains how to work properly with async code https://www.youtube.com/watch?v=obaSQBBWZLk. It could help you with this and another stuff.

Edit 2: Using promises would be like this, see if it helps you:

var Q = require("q");

app.use('/', function (req, res, next) {

    // This part, we will call your function "makeLoginCookie"
    makeLoginCookie().then(function(){
        // This is called when your function RESOLVES the promise

        // Here you could log or do some stuff...

        // Then, go next...
        next();
    }, function(error){
        // This is called when your function REJECTS the promise
        console.log("Connect failed %s" , error);

        // And then, handle the error, like stopping the request and sending an error:
        res.status(400).json({errorMessage: error});
    })
}, function (req, res, next){
    console.log('My app.use() starts here.');
    next(); 
});

// Removed parameters from function
function makeLoginCookie() {
    // This is the object that will return a promise
    var deferred = Q.defer();

    httpOptions = {
        url: site.url,
        headers: {
            Cookie: null
        }
    }

    // Get HIDDEN key, build login cookie
    request(httpOptions, function(error, response, body) {
        if (!error && response.statusCode == 200) {
            //console.log(body)
            var match = body.match( /\<INPUT TYPE=HIDDEN id=\"key\", value=\"([0-9a-f]+)\"\>/i );
            var key = match[1]
            var encrypted = sha1(key + site.username + site.password);
            loginCookie = "username=" + key + ";password=" + encrypted;

            // Instead of using next(), RESOLVE your promise
            // next();
            deferred.resolve(); // You can pass some data into it..
        } else {

            // Instead of using next(), REJECT your promise
            // next();
            deferred.reject(error); // You can pass some data into it, like an error object or string...
        }
    });

    // Promise that something will be fulfilled or reject later
    return deferred.promise;
};

Upvotes: 0

zangw
zangw

Reputation: 48536

Refer to Express Error handling, you can use next(err); to pass error in Express. Here is one good link.

Upvotes: 3

Related Questions