简体   繁体   中英

Can't set headers after they are sent in express js

I looked around at previous answers to this question, but I don't understand why is this error coming up if there are res.send() in multiple paths.

My code is something like this (expressjs 4.13):

var user ={
    username: "some",
    password: "a"
}

router.post('/login', authenticate, function (req, res) {
    //if it passes the middleware, send back the user

    var token = jwt.sign({
        username: user.username
    }, jwtSecret);
    res.send({
         token: token,
        user: user
    });
});

function authenticate(req, res, next) {
    var body = req.body;
    var username = body.username, password = body.password;

    //if nothing is sent
    if(!username || !password){
        res.status(400).end('Must send a user and pass');
    }

    //if incorrect credentials are sent
    if(username !== user.username || password !== user.password){
        res.status(401).end("Incorrect credentials");
    }

    //if it reaches here, it means credentials are correct
    next();
}

When I don't send anything from my frontend, I am getting the 400 and error message, but my server shows this:

POST /apis/auth/login 401 0.841 ms - -
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)
at ServerResponse.header     (/home/vivek/dev/qwiksplit/jsback/node_modules/express/lib/response.js:718:10)
at ServerResponse.json (/home/vivek/dev/qwiksplit/jsback/node_modules/express/lib/response.js:246:10)
at ServerResponse.send (/home/vivek/dev/qwiksplit/jsback/node_modules/express/lib/response.js:151:21)
at /home/vivek/dev/qwiksplit/jsback/app.js:81:9
at Layer.handle_error (/home/vivek/dev/qwiksplit/jsback/node_modules/express/lib/router/layer.js:71:5)
at trim_prefix (/home/vivek/dev/qwiksplit/jsback/node_modules/express/lib/router/index.js:310:13)
at /home/vivek/dev/qwiksplit/jsback/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/home/vivek/dev/qwiksplit/jsback/node_modules/express/lib/router/index.js:330:12)
at next (/home/vivek/dev/qwiksplit/jsback/node_modules/express/lib/router/index.js:271:10)

I am not sure how I am setting headers after a response is sent.

确保退货!

return res.status(400).end('Must send a user and pass');

In your middleware function, you need to make sure next() is not called after you've already sent a response (eg, by calling res.send() , res.end() or similar).

The simplest solution is to just return from your middleware right after you've sent a response:

function authenticate(req, res, next) {
    var body = req.body;
    var username = body.username, password = body.password;

    if(!username || !password){
        res.status(400).end('Must send a user and pass');
        return; // <-----
    }

    if(username !== user.username || password !== user.password){
        res.status(401).end("Incorrect credentials");
        return; // <-----
    }

    next();
}

You are missing some return statements. If you don't return from the function status and send gets called multiple times on your response object, and at the end even next is called as well, so the upcoming middlewares will operate on the response too.

function authenticate(req, res, next) {
    var body = req.body;
    var username = body.username, password = body.password;

    //if nothing is sent
    if(!username || !password){
        res.status(400).end('Must send a user and pass');
        return;
    }

    //if incorrect credentials are sent
    if(username !== user.username || password !== user.password){
        res.status(401).end("Incorrect credentials");
        return;
    }

    //if it reaches here, it means credentials are correct
    next();
}

Please make sure to add return statement after this code

    res.status(400).end('Must send a user and pass');

It can be

    return; or return res.status(400).end('Must send a user and pass');

Just return anything after that line, basically stop execution of your code after that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM