Express:发送后无法设置标头

时间:2016-01-25 13:23:17

标签: node.js express http-headers cors

以下是我的服务器文件。我正在打2个电话,一个帖子和一个电话。它有时很好用。但是给出了一个错误:发送后不能设置标头。这与我的客户端代码有什么关系吗?

server.js

var express    = require('express')
var mongoose   = require('mongoose')
var path       = require('path')
var bodyParser = require("body-parser")
var cors       = require("cors")
var app        = express()
var port       = process.env.PORT || 3000
var Url        = require("./data/url-schema");


//Express request pipeline
app.use(express.static(path.join(__dirname,"../client")))
app.use(bodyParser.json())
app.use(cors());

/*
Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response.
 */
app.get('*', function (request, response, next){
  response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
  next()
})

app.get('/:code', function(req, res) {
    console.log("reg", req.params.code)
    Url.findOne({code:req.params.code}, function(err, data){
    console.log("data", data)
    if(data)
            res.redirect(302, data.longUrl)
        else
            res.end()
    })
})

app.post('/addUrl', function (req, res, next) {
    console.log("on create");
    Url.findOne({longUrl:req.body.longUrl}, function(err, data) {
    if (err)
      res.send(err);
    else if(data) {
        console.log("already exists",data)
      res.send("http://localhost:3000/"+data.code);
    } else {
            var url = new Url({
                code    : Utility.randomString(6,"abcdefghijklm"),
                longUrl : req.body.longUrl
              });
            console.log("in last else data created",url)
              url.save(function (err, data) {
                console.log(data)
                if (err)
                  res.send(err);
                else
                  res.send("http://localhost:3000/"+data.code);
              });
            }
    });
})

app.listen(port, function () {
  console.log('Example app listening on port 3000!')
});

// Connect to our mongo database
mongoose.connect('mongodb://localhost/shortUrl');

我收到以下错误

错误

_http_outgoing.js:335
    throw new Error('Can\'t set headers after they are sent.');
          ^
Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
    at ServerResponse.header (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:718:10)
    at ServerResponse.location (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:835:8)
    at ServerResponse.redirect (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:874:8)
    at Query.<anonymous> (/opt/lampp/htdocs/url-shortener/server/server.js:30:8)
    at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:177:19
    at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:109:16
    at process._tickCallback (node.js:355:11)

2 个答案:

答案 0 :(得分:1)

从执行顺序,在*路由处理程序中,正在将主体分配给响应,然后在/:code中添加响应代码302,其中{{1标题也被添加,因此错误。任何标题必须在正文之前添加到响应中。

要解决此问题,只需更改两个GET语句的顺序。

答案 1 :(得分:0)

终于找到了解决方案:

var express    = require('express')
var mongoose   = require('mongoose')
var path       = require('path')
var bodyParser = require("body-parser")
var app        = express()
var port       = process.env.PORT || 3000
var Url        = require("./data/url-schema")
var Utility    = require("./utility")

//Express request pipeline
app.use(express.static(path.join(__dirname,"../client")))
app.use(bodyParser.json())

/*
Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response.
 */
app.get('/dashboard', function (request, response, next){
  response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
  next()
})
app.get('/about', function (request, response, next){
  response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
  next()
})

app.get('/:code', function(req, res) {
    Url.findOne({code:req.params.code}, function(err, data){
    if(data){
            res.redirect(302, data.longUrl)
    }
    })
})

app.post('/addUrl', function (req, res, next) {
    Url.findOne({longUrl:req.body.longUrl}, function(err, data) {
    if (err){
      res.send(err)
    }
    else if(data) {
      res.send("http://localhost:3000/"+data.code);
    } else {
            var newCode = getCode()
            checkCode(newCode)
            .then(function(data){
                var url = new Url({
                    code    : data,
                    longUrl : req.body.longUrl
                  });
                  url.save(function (err, data) {
                    if (err)
                      res.send(err);
                    else
                      res.send("http://localhost:3000/"+data.code);
                  });
            })
            }
    });
})

app.listen(port, function () {
  console.log('Example app listening on port 3000!')
});

// Connect to our mongo database
mongoose.connect('mongodb://localhost/shortUrl');

//Generate a random code
function getCode() {
    return Utility.randomString(6,"abcdefghijklmnopqrstuvwxyz")
}

//Check if the code is unique
function checkCode(code) {
    return new Promise(function (resolve, reject){
        Url.findOne({code:code}, function(err, data) {
            if(err === null){
                resolve(code)
            }else if(data){
                saveUrlCode(getCode())
            }
        })
    })
}

我之前的路线是:

app.get('*', function (request, response, next){
  response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
  next()
})

由于上述调用而且获取路由被执行了两次 app.get(“:/ code”)调用。 所以我必须通过单独处理仪表板和路线而不是使用“*”路线来正确处理我所做的路线。