I am working on an express-based nodejs application. I need to authenticate users for login with the help of a third-party site. Overall, theres a client (written by me), a server (written by me, in nodejs), and this third-party API that I must use for validating users.
The steps are roughly:
- The client sends the server a request with a ticket (hash)
- If the user is not already logged in, the server sends q request to the third-party API to validate the user
- If the third-party site says the login is OK, return a
NEW_LOGIN_ACCEPT
reply to the client - Else, return
FAIL
to the client
I am having trouble figuring out how to properly structure this with nodejs. I need to wait on sending the response to the client until the request to the third-party API has completed. My understanding is that blocking requests is not the "right" way to do things in node, and instead I should utilize callbacks. I cannot get the callbacks to work right.
The server-side code for handling this request is below, with some slight modifications made:
app.get('/login', function (req, res, next) {
ticket = req.query.ticket;
if (! has_valid_session(ticket)) {
request(third_party_api_url + '&ticket=' + ticket,
function (error, response, body) {
if (body.indexOf('authenticationSuccess') != -1) {
add_session('example_username', 'example_id');
res.send('NEW_LOGIN_ACCEPT');
} else {
res.send('FAIL');
}
});
} else {
res.send('SESSION_OK');
session_activity(username);
}
next();
});
The problem is that the response (res
) has already been sent back to the client by the time the callback is hit. The error I get is:
_http_outgoing.js:500
throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I realize the "node-ic" way of doing things is via promises/callbacks, but I cant figure out how to keep the response (res
) alive through a chain of callbacks.
I looked at the answer to this question: Wait for request to finish Node.js which seems like a similar thing, but I'm not sure if/how that would work for me.