【问题标题】:Can't set headers after they are sent in express js以 express js 发送后无法设置标头
【发布时间】:2016-09-02 20:29:46
【问题描述】:

我查看了此问题的先前答案,但我不明白如果多个路径中有res.send(),为什么会出现此错误。

我的代码是这样的(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();
}

当我不从前端发送任何内容时,我收到 400 和错误消息,但我的服务器显示:

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)

我不确定在发送响应后如何设置标头。

【问题讨论】:

    标签: javascript node.js express


    【解决方案1】:

    请务必返回!

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

    【讨论】:

    • 这是有道理的。我假设当我说 res.send() 或 res.end() 时,执行将在那里停止并且默认返回。
    • 响应结束但后面的代码仍会执行expressjs.com/en/api.html#res.end
    • 除此之外,Express 中所做的一切都是“中间件”,甚至是最后一个回调。因此,当您在 authenticate 中间件中调用 next() 时,您在 router.post 中提供的回调(也是中间件)仍然运行并尝试运行 res.send,即使响应已经发送,这会导致错误。
    【解决方案2】:

    在您的中间件函数中,您需要确保在您已经发送响应(例如,通过调用 res.send()res.end() 或类似方法)之后调用 next()

    最简单的解决方案是在您发送响应后立即从中间件返回:

    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();
    }
    

    【讨论】:

      【解决方案3】:

      您缺少一些返回语句。如果你没有从函数status 中返回,send 在你的response 对象上被多次调用,最后甚至next 也被调用,所以即将推出的中间件也会对响应进行操作.

      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();
      }
      

      【讨论】:

        【解决方案4】:

        请务必在此代码后添加return语句

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

        可以

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

        在该行之后返回任何内容,然后基本上停止执行您的代码。

        【讨论】:

          猜你喜欢
          • 2018-05-05
          • 2017-08-11
          • 2016-12-19
          • 1970-01-01
          • 1970-01-01
          • 2019-01-14
          • 1970-01-01
          • 2017-03-03
          • 2012-08-01
          相关资源
          最近更新 更多