Error: Can't set headers after they are sent to the client
我刚接触node.js,遇到了一些问题。
我使用的是node.js 4.10和express 2.4.3。
当我尝试访问http://127.0.0.1:8888/auth/facebook时,我将被重定向到http://127.0.0.1:8888/auth/facebook_回调。
然后我收到以下错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | Error: Can't render headers after they are sent to the client. at ServerResponse. (http.js:573:11) at ServerResponse._renderHeaders (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:64:25) at ServerResponse.writeHead (http.js:813:20) at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/auth.strategies/facebook.js:28:15 at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:113:13 at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/strategyExecutor.js:45:39) at [object Object].pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:32:3) at [object Object].halt (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:29:8) at [object Object].redirect (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:16:8) at [object Object]. (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/auth.strategies/facebook.js:77:15) Error: Can't set headers after they are sent. at ServerResponse. (http.js:527:11) at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:195:11) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23) at param (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:189:13) at pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:191:10) at Object.router [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:197:6) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15) at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7) Error: Can't set headers after they are sent. at ServerResponse. (http.js:527:11) at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23) at param (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:189:13) at pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:191:10) at Object.router [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:197:6) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15) at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7) Error: Can't set headers after they are sent. at ServerResponse. (http.js:527:11) at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9) at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15) at HTTPServer.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:211:3) at Object.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:105:14) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15) Error: Can't set headers after they are sent. at ServerResponse. (http.js:527:11) at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9) at HTTPServer.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:211:3) at Object.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:105:14) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15) at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:323:9 at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:338:9 node.js:134 throw e; // process.nextTick error, or 'error' event on first tick ^ Error: Can't set headers after they are sent. at ServerResponse. (http.js:527:11) at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9) at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:323:9 at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:338:9 at Array. (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session/memory.js:57:7) at EventEmitter._tickCallback (node.js:126:26) |
以下是我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | var fbId="XXX"; var fbSecret="XXXXXX"; var fbCallbackAddress="http://127.0.0.1:8888/auth/facebook_callback" var cookieSecret ="node"; // enter a random hash for security var express= require('express'); var auth = require('connect-auth') var app = express.createServer(); app.configure(function(){ app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.cookieParser()); app.use(express.session({secret: cookieSecret})); app.use(auth([ auth.Facebook({ appId : fbId, appSecret: fbSecret, callback: fbCallbackAddress, scope: 'offline_access,email,user_about_me,user_activities,manage_pages,publish_stream', failedUri: '/noauth' }) ])); app.use(app.router); }); app.get('/auth/facebook', function(req, res) { req.authenticate("facebook", function(error, authenticated) { if (authenticated) { res.redirect("/great"); console.log("ok cool."); console.log(res['req']['session']); } }); }); app.get('/noauth', function(req, res) { console.log('Authentication Failed'); res.send('Authentication Failed'); }); app.get('/great', function( req, res) { res.send('Supercoolstuff'); }); app.listen(8888); |
我可以知道我的代码有什么问题吗?
express中的
错误"error:can't set headers after them a re sent."表示您已经处于正文或完成状态,但某些函数试图设置标题或状态代码。当您看到此错误时,请尝试在某些正文已写入之后查找任何试图发送标题的内容。例如,查找意外调用两次的回调,或在发送正文后发生的任何错误。
在您的案例中,您调用了
响应必须在头部,并保持在头部:
响应必须在头部,并成为身体:
响应可以在头部/身体中,也可以留在身体中:
响应可以在头部/身体中进行,并完成:
响应可以是头部/身体,并保持其当前状态:
响应必须在头中并完成:
我也有一段时间遇到了这个错误。我想(希望)我已经把我的头缠在上面了,想把它写在这里作为参考。
当您使用
问题是,如果在某个中间件项中写入响应主体或报头(看起来是/或出于某种原因),但不调用
所以,它抛出了一个错误。但它抛出的错误只是这个基本响应(来自connect
1 2 3 | res.statusCode = 404; res.setHeader('Content-Type', 'text/plain'); res.end('Cannot ' + req.method + ' ' + req.url); |
在这里,它调用
1 2 3 4 | response.setHeader("Content-Type","text/html"); response.write("<p> Hello World </p>"); |
所有东西的结构都是这样的:
好的中间件1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // middleware that does not modify the response body var doesNotModifyBody = function(request, response, next) { request.params = { a:"b" }; // calls next because it hasn't modified the header next(); }; // middleware that modify the response body var doesModifyBody = function(request, response, next) { response.setHeader("Content-Type","text/html"); response.write("<p> Hello World </p>"); response.end(); // doesn't call next() }; app.use(doesNotModifyBody); app.use(doesModifyBody); |
有问题的中间件
1 2 3 4 5 6 7 | var problemMiddleware = function(request, response, next) { response.setHeader("Content-Type","text/html"); response.write("<p> Hello World </p>"); next(); }; |
有问题的中间件在不调用
我也遇到了同样的问题,我意识到这是因为我打电话给
1 2 3 4 | auth.annonymousOnly = function(req, res, next) { if (req.user) res.redirect('/'); next(); }; |
应该是:
1 2 3 4 | auth.annonymousOnly = function(req, res, next) { if (req.user) return res.redirect('/'); next(); }; |
很多人都犯了这个错误。这与异步处理混淆了。很可能您的一些代码是在第一个标记中设置头,然后在将来的标记中运行异步回调。在这两者之间,将发送响应头,但随后会发送更多的头(如30x重定向),尝试添加额外的头,但由于响应头已被传输,因此为时已晚。
我不确定究竟是什么导致了你的错误,但是把任何回调看作是潜在的调查领域。
简化代码的一个简单提示。去掉
另请参阅EveryAuth模块,它提供Facebook和十几个其他第三方认证提供商。
此问题中的某些答案是错误的。接受的答案也不是很"实用",所以我想发布一个简单的答案来解释问题。我的答案将涵盖99%的错误,我看到张贴一遍又一遍。对于错误背后的实际原因,请查看接受的答案。
HTTP使用的循环要求每个请求一个响应。当客户机发送请求(例如POST或GET)时,服务器应该只向其发送一个响应。
此错误消息:
Error: Can't set headers after they are sent.
通常在您为一个请求发送多个响应时发生。确保每个请求只调用一次以下函数:
res.json() res.send() res.redirect() res.render()
(还有一些很少使用的答案,请检查接受的答案)
调用这些res函数时,路由回调不会返回。它将继续运行,直到到达函数或返回语句的末尾。如果您想在发送响应时返回,可以这样做:
以该代码为例:
1 2 3 4 5 6 | app.post('/api/route1', function(req, res) { console.log('this ran'); res.status(200).json({ message: 'ok' }); console.log('this ran too'); res.status(200).json({ message: 'ok' }); } |
当post请求发送到/api/route1时,它将运行回调中的每一行。发送邮件后无法设置邮件头将引发错误消息,因为
每个请求只能发送一个响应!
上面的代码示例中的错误是明显的。一个更典型的问题是当您有几个分支时:
1 2 3 4 5 6 7 8 9 10 11 | app.get('/api/company/:companyId', function(req, res) { const { companyId } = req.params; Company.findById(companyId).exec((err, company) => { if (err) { res.status(500).json(err); } else if (!company) { res.status(404).json(); // This runs. } res.status(200).json(company); // This runs as well. }); } |
此带有附加回调的路由在数据库中查找公司。当查询一个不存在的公司时,我们将进入
1 2 3 4 5 6 7 8 9 | .exec((err, company) => { if (err) { res.status(500).json(err); } else if (!company) { res.status(404).json(); // Only this runs. } else { res.status(200).json(company); } }); |
或者在发送响应时返回:
1 2 3 4 5 6 7 8 | .exec((err, company) => { if (err) { return res.status(500).json(err); } else if (!company) { return res.status(404).json(); // Only this runs. } return res.status(200).json(company); }); |
异步函数是最大的罪魁祸首。以这个问题中的函数为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | article.save(function(err, doc1) { if (err) { res.send(err); } else { User.findOneAndUpdate({ _id: req.user._id }, { $push: { article: doc._id } }) .exec(function(err, doc2) { if (err) res.send(err); else res.json(doc2); // Will be called second. }) res.json(doc1); // Will be called first. } }); |
这里我们在代码示例中有一个异步函数(
在这种情况下,解决方法是删除
我对这个问题很生气,它是由于处理回拨时的一个粗心错误而发生的。未返回的回调会导致响应设置两次。!
我的程序有一个代码,用于验证请求并查询数据库。在验证是否存在错误之后,我用验证错误回调index.js。如果验证通过,则继续进行,并成功/失败地命中数据库。
1 2 3 4 5 6 | var error = validateRequestDetails("create",queryReq); if (error) callback(error, null); else some code callback(null, success); |
发生的是:如果验证失败,将调用回调并设置响应。但没有返回。所以它仍然继续,方法转到数据库,并命中成功/失败。它再次调用同一个回调,导致响应现在被设置两次。
所以解决方案很简单,您需要"返回"回调,这样一旦发生错误,该方法就不会继续执行,从而将响应对象设置一次
1 2 3 4 5 6 7 | var error = validateRequestDetails("create",queryReq); if (error) callback(error, null); return; else some code callback(null, success); |
当发送响应后传递语句时,会出现这种类型的错误。
例如:
1 2 3 4 | res.send("something response"); console.log("jhgfjhgsdhgfsdf"); console.log("sdgsdfhdgfdhgsdf"); res.send("sopmething response"); |
将导致您看到的错误,因为一旦发送响应,将不会执行以下
如果你想做什么,你应该在发送响应之前做。
有时,当您尝试在res.end或res.send之后调用next()函数时,可能会出现此错误。如果函数中有res.send或res.end之后的next(),请尝试删除此错误。注意:这里的next()意味着在用您的响应(即res.send或res.end)响应客户机之后,您仍在尝试执行一些代码以再次响应,因此这是不合法的。
例子:
1 2 3 4 | router.get('/',function (req,res,next){ res.send("request received"); next(); // this will give you the above exception }); |
remove
next() from above function and it will work.
在我的例子中,当我没有从我的react组件的
在我的例子中,是一个304响应(缓存)导致了这个问题。
最简单的解决方案:
1 | app.disable('etag'); |
如果您想要更多的控制,请选择这里的替代解决方案:
http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoint-304-not-modified/
当响应被传递到客户机,并且您再次尝试给出响应时,就会发生这种情况。您必须签入代码,在某个地方您将再次返回对客户端的响应,这将导致此错误。当您想要返回时,请检查并返回一次响应。
只是靠着这个。您可以通过此函数传递响应:
1 2 3 4 5 6 7 8 9 10 | app.use(function(req,res,next){ var _send = res.send; var sent = false; res.send = function(data){ if(sent) return; _send.bind(res)(data); sent = true; }; next(); }); |
对于任何正在进行此操作且其他解决方案都不起作用的人,在我的示例中,这表现在处理图像上载但不处理超时的路由上,因此,如果上载时间过长且超时,则在发送超时响应后触发回调时,调用res.send()会导致作为头服务器的崩溃。e已经设置为超时。
通过设置一个非常短的超时,并以一个相当大的图像点击路线,很容易重现这一点,每次都会重现崩溃。
添加这个中间件,它就可以工作了
1 2 3 4 5 6 7 8 9 10 | app.use(function(req,res,next){ var _send = res.send; var sent = false; res.send = function(data){ if(sent) return; _send.bind(res)(data); sent = true; }; next(); }); |
来自nuxt的问题是组件的
在typescript中,我的问题是在收到消息后没有关闭WebSocket连接。
1 2 3 4 5 | WebSocket.on("message", (data) => { receivedMessage = true; doSomething(data); localSocket.close(); //This close the connection, allowing }); |
很可能这更像是一个节点,99%的时候它是一个双回调,导致您响应两次,或者下一次()调用两次等等,当然。它解决了我在循环中使用next()的问题。从循环中移除next()或停止多次调用它。
如果你得不到上面的帮助,那就是:为无意义的人。此错误背后的原因是多次发送请求,让我们从某些情况下了解到:1。`
1 2 3 4 5 6 7 8 9 10 | module.exports = (req,res,next)=>{ try{ const decoded = jwt.verify(req.body.token,"secret"); req.userData = decoded; next(); }catch(error){ return res.status(401).json({message:'Auth failed'}); } next(); } |
`在上面调用next()两次将引发错误
router.delete('/:orderId', (req, res, next) => {
Order.remove({_id:req.params.orderId},(err,data)=>{
if(err){
**res.status(500).json(err);**
}else{
res.status(200).json(data);
}
*res.status(200).json(data);*
})
})
这里的响应是发送两次检查您是否已经发送了响应
我做承诺的时候就有这个问题。承诺中的承诺将返回200到服务器,但外部承诺的catch语句将返回500。一旦我解决了这个问题,问题就消失了。
在我的例子中,它是由于多次回调而发生的。我在代码期间多次调用了
在出现这个错误的情况下,我所要做的就是res.end()。
1 2 3 4 | auth.annonymousOnly = function(req, res, next) { // add other task here res.end(); }; |
您可能面临的另一个问题是在res.json和res.write之后有代码。在这种情况下,您需要使用返回来停止执行。
1 2 3 4 5 6 7 8 9 | auth.annonymousOnly = function(req, res, next) { if(!req.body.name) { res.json({error:"some error"}); return; } let comp ="value"; // this is the code after res.json which may cause some problems so you have to use return }; |
请检查您的代码是否为单个请求返回多个res.send()语句。就像我遇到这个问题时……
我在我的restify节点应用程序中遇到了这个问题。错误是
case -1:
res.send(400);
case 0:
res.send(200);
default:
res.send(500);
}
我在处理各种各样的案件时使用了开关,没有写断。对于那些不太熟悉开关盒的人来说,知道不间断地返回关键字。无论发生什么,case下的代码及其下一行都将被执行。因此,尽管我想发送单个res.send,但由于这个错误,它返回了多个res.send语句,提示
error cant set headers after they are sent to the client. Which got resolved by adding this or using return before each res.send() method like return res.send(200)
case -1:
res.send(400);
break;
case 0:
res.send(200);
break;
default:
res.send(500);
break;
}