Search code examples
node.jsnode-rest-client

node-rest-client: Can't set headers after they are sent.


I am trying to call a REST API from node using node-rest-client. In the event that my call returns an error, I want to catch the error and report it to the caller.

I am trying this with Postman, unfortunately this only works once. When I press send the second time, my node.js program crashes with the error "Can't set headers after they are sent."

I am new at node.js, so any help is highly appreciated!

//app stuff
const client_id = "x";
const client_secret = "y";
const callback = "https://myurl;

// Basic Setup
var http     = require('http'),
    express  = require('express'),
    mysql    = require('mysql'),
    parser   = require('body-parser'),
    Client   = require('node-rest-client').Client;

var client = new Client();

// Setup express
var app = express();
app.use(parser.json());
app.use(parser.urlencoded({ extended: true }));
app.set('port', process.env.PORT || 5000);

// Set default route
app.get('/', function (req, res) {
    res.send('<html><body><p>Welcome to Bank API Wrapper</p></body></html>');
});

app.post('/authorize', function (req,res) {
    var response = [];

    if (typeof req.body.code !== 'undefined' && typeof req.body.state !== 'undefined' ){
        var code = req.body.code, state = req.body.state;

        //conversion to base64 because citi api wants it this way
        var authorization = "Basic " + Buffer.from(client_id + ":" + client_secret).toString('base64');

        var args = {
            data:{"grant_type":"authorization_code","code":code,"redirect_uri":callback},
            headers:{"Authorization":authorization,"Content-Type":"application/x-www-form-urlencoded"} 
        };

        //get access and refresh token
        client.post("https://sandbox.apihub.citi.com/gcb/api/authCode/oauth2/token/sg/gcb", args, function (citidata, citiresponse) {
            //console.log(citidata);
            //console.log(citiresponse);
        });

        client.on('error', function (err) {
            response.push({'result' : 'error', 'msg' : 'unauthorized access'});
            res.setHeader('Content-Type', 'application/json');
            res.status(200).send(JSON.stringify(response));
        });
    } 
    else {
        response.push({'result' : 'error', 'msg' : 'Please fill required details'});
        res.setHeader('Content-Type', 'application/json');
        res.status(200).send(JSON.stringify(response));
    }
});


// Create server
http.createServer(app).listen(app.get('port'), function(){
    console.log('Server listening on port ' + app.get('port'));
});

Solution

  • You've got this:

    client.on('error', function (err) {
    

    This register an error handler on the client but it never gets removed. The client is shared between requests so any errors on subsequent requests will still fire the old error handlers.

    Instead you can listen for an error on the request. Something like this:

    var request = client.post("...
    
    request.on('error', function(err) {
        // handle error
    });
    

    See https://www.npmjs.com/package/node-rest-client#error-handling