Express重定向错误:无法在发送响应后设置标头

13
当这段代码执行重定向操作时,会抛出“无法在发送后设置标头”的错误,并且不会重定向。我承认自己没有完全理解标头以及Express如何使用它们。关于此错误的此链接有点令我困惑,可能是因为我对正在发生的事情缺乏基本的了解。此外,我知道这种身份验证方法有点幼稚,但我只是想让基本的东西工作。
    app.post('/api/login', function(req, res) {
    if (req.body.password === auth.password) {
        auth.date = new Date()
        res.redirect('/admin')
      } else {
        console.log("wrong pw")
      }
    })

更新:感谢@Brendan Ashworth指出了一个明显的else问题,我已经添加了该语句,不再出现错误。

然而,这一行并没有改变我的页面内容。

res.sendfile('./public/admin/views/tunes.html')

在加上身份验证检查之前,它是有效的。

var auth = require('../config/auth')

module.exports = function(app) {

/*
 *  CONTENT API
 */

 //...

/*
 *  Admin Routes
 */
app.get('/admin/login', function(req, res) {
    res.sendfile('./public/admin/views/login.html')
})

app.post('/api/login', function(req, res) {
    if (req.body.password === auth.password) {
        auth.date = new Date()
        res.redirect('/admin')
    } else {
        res.json({message: 'Wrong password!'})
    }
})

app.get('/admin', function(req, res) {
    if (auth.date) {
        res.sendfile('./public/admin/views/tunes.html')
        console.log("test") // 
    } else { //added else
      res.redirect('/admin/login')
    }
})

app.get('/admin/:url', function(req, res) {
    if (auth.date) {
        res.sendfile('./public/admin/views/' + req.params.url + '.html')
    } else { //added else
      res.redirect('/admin/login')
    }
})

// frontend routes 
// route to handle all angular requests
app.get('*', function(req, res) {
    res.sendfile('./public/views/index.html') 
})

最终更新!我需要处理发送文件后客户端的重定向。现在简单的身份验证已经完美运行!

    $http.post('/api/login', $scope.auth).success(function() {
        window.location.href = '/admin'
    })

你能展示一下你的其他路由和中间件吗?另外,值得注意的是,如果 res.body.password 不等于 auth.password,在你发布的代码中将永远不会发送响应。 - Paul
在这个中间件之前,你是否有其他的路由或中间件调用了res.writeHead()res.send()res.write()或类似的方法? - mscdex
@Paul 谢谢,已将 console.log 更改为 res.json,并添加了更多的代码。 - azium
2个回答

12

“无法在发送头信息后设置头信息”的错误解释:

所有的HTTP响应都遵循这个基本结构:

.. Response Line ..
.. Headers ..

.. Body ..

如果您想要重定向用户,首先会发送一个重定向代码(比如说300)的响应行,然后会发送包含Location: xxx头的标头。接下来,我们最终可以发送正文(不适用于重定向,但通常是这样)。然而,在您的代码中,由于您发送了正文,之后再尝试重定向用户,因此已经发送了标头(和响应行),无法在正文后发送更多标头。您代码中的示例可能是这样的:
app.get('/admin', function(req, res) {
    if (auth.date) {
        res.sendfile('./public/admin/views/tunes.html')
    }
    res.redirect('/admin/login')
})

如果我猜得没错,您实际上想在res.sendfile()调用后返回。如果auth.date是真值,那么您将发送一个文件(即正文响应),然后给出重定向代码-这是行不通的。

1
@self 不就是我输入的吗? - Brendan
这节省了我很多时间,将res.redirect后面添加return解决了我的问题。 - Dimitar Nikovski

0

重定向后只需调用res.stop();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接