Dja*_*cks 645 javascript node.js express
我是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_callback.
然后我收到以下错误:
Error: Can't render headers after they are sent to the client.
at ServerResponse.<anonymous> (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].<anonymous> (/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.<anonymous> (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.<anonymous> (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.<anonymous> (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.<anonymous> (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.<anonymous> (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.<anonymous> (/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)
Run Code Online (Sandbox Code Playgroud)
以下是我的代码:
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);
Run Code Online (Sandbox Code Playgroud)
我可以知道我的代码有什么问题吗?
yon*_*ran 988
resExpress中的对象是Node.js的http.ServerResponse子类(读取http.js源代码).您可以随时拨打电话res.setHeader(name, value),直到您打电话为止res.writeHead(statusCode).之后writeHead,标题被烘焙,您只能调用res.write(data),最后res.end(data).
错误"错误:发送后无法设置标头".表示您已处于Body或Finished状态,但某些函数尝试设置标题或statusCode.当您看到此错误时,尝试查找在已经写入某些正文后尝试发送标头的任何内容.例如,查找意外调用两次的回调,或发送正文后发生的任何错误.
在你的情况下,你打电话res.redirect(),导致响应成为完成.然后你的代码抛出一个错误(res.req是null).并且由于错误发生在您的实际内function(req, res, next)(不在回调中),Connect能够捕获它,然后尝试发送500错误页面.但由于标题已经发送,Node.js setHeader抛出了你看到的错误.
回复必须在Head并保持在Head:
res.writeContinue()res.statusCode = 404res.setHeader(name, value)res.getHeader(name)res.removeHeader(name)res.header(key[, val]) (仅限快递)res.charset = 'utf-8' (仅限Express;仅影响特定于Express的方法)res.contentType(type) (仅限快递)响应必须在Head并成为Body:
响应可以在头部/身体中,并保留在身体中:
响应可以在头部/身体中完成并且完成:
响应可以在头部/身体中,并保持其当前状态:
响应必须在Head并且已完成:
return next([err]) (仅限连接/快速)function(req, res, next)(仅限Connect/Express)res.send(body|status[, headers|status[, status]]) (仅限快递)res.attachment(filename) (仅限快递)res.sendfile(path[, options[, callback]]) (仅限快递)res.json(obj[, headers|status[, status]]) (仅限快递)res.redirect(url[, status]) (仅限快递)res.cookie(name, val[, options]) (仅限快递)res.clearCookie(name[, options]) (仅限快递)res.render(view[, options[, fn]]) (仅限快递)res.partial(view[, options]) (仅限快递)Lan*_*ard 97
我也遇到了这个错误一段时间.我想(希望)我已经把它包裹起来,想把它写在这里作为参考.
当您使用该方法添加中间件来连接或表达(建立在连接上)时app.use,您将Server.prototype.stack在连接中附加项目(至少使用当前npm install connect,这与本文中的一个github完全不同).当服务器获取请求时,它会遍历堆栈,调用该(request, response, next)方法.
问题是,如果其中一个中间件项目写入响应主体或标题(它看起来像是/或由于某种原因),但是没有调用response.end(),next()然后在核心Server.prototype.handle方法完成时调用,它会注意到那:
response.headerSent是真的.所以,它会抛出一个错误.但它抛出的错误只是这个基本的响应(来自连接http.js源代码:
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('Cannot ' + req.method + ' ' + req.url);
Run Code Online (Sandbox Code Playgroud)
就在那里,它正在调用res.setHeader('Content-Type', 'text/plain');,你可能已经在你的render方法中设置了,而没有调用response.end(),例如:
response.setHeader("Content-Type", "text/html");
response.write("<p>Hello World</p>");
Run Code Online (Sandbox Code Playgroud)
一切都需要结构化的方式是这样的:
// 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);
Run Code Online (Sandbox Code Playgroud)
var problemMiddleware = function(request, response, next) {
response.setHeader("Content-Type", "text/html");
response.write("<p>Hello World</p>");
next();
};
Run Code Online (Sandbox Code Playgroud)
有问题的中间件设置响应头而不调用response.end()和调用next(),这会混淆connect的服务器.
erg*_*sto 47
我有同样的问题并且意识到这是因为我在res.redirect没有return声明的情况下进行调用,所以next之后也立即调用了该函数:
auth.annonymousOnly = function(req, res, next) {
if (req.user) res.redirect('/');
next();
};
Run Code Online (Sandbox Code Playgroud)
应该是:
auth.annonymousOnly = function(req, res, next) {
if (req.user) return res.redirect('/');
next();
};
Run Code Online (Sandbox Code Playgroud)
Mik*_*kaS 38
本问答中的一些答案是错误的.接受的答案也不是很"实用",所以我想发一个用简单的术语解释事情的答案.我的回答将涵盖我一遍又一遍地发布的99%的错误.对于错误背后的实际原因,请查看已接受的答案.
HTTP使用一个循环,每个请求需要一个响应.当客户端发送请求(例如POST或GET)时,服务器应该只发回一个响应.
此错误消息:
错误:发送后无法设置标头.
通常在您为一个请求发送多个响应时发生.确保每个请求仅调用以下函数一次:
res.json()res.send()res.redirect()res.render()(以及一些很少使用的,请检查接受的答案)
调用这些res函数时,不会返回路由回调.它将继续运行,直到它到达函数结束或返回语句.如果你想在发送回复时返回,你可以这样做:return res.send().
以此代码为例:
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' });
}
Run Code Online (Sandbox Code Playgroud)
当POST请求发送到/ api/route1时,它将运行回调中的每一行.A 发送后不能设置标头错误消息将被抛出,因为res.json()被调用两次,这意味着发送了两个响应.
每个请求只能发送一个响应!
上面的代码示例中的错误是显而易见的.更典型的问题是当你有几个分支时:
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.
});
}
Run Code Online (Sandbox Code Playgroud)
带有附加回调的此路由在数据库中查找公司.在对不存在的公司进行查询时,我们将进入else if分支并发送404响应.之后,我们将继续下一个也发送回复的声明.现在我们发送了两个响应,并将出现错误消息.我们可以通过确保只发送一个响应来修复此代码:
.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);
}
});
Run Code Online (Sandbox Code Playgroud)
或者在发送回复时返回:
.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);
});
Run Code Online (Sandbox Code Playgroud)
一个大罪人是异步功能.从这个问题中获取函数,例如:
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.
}
});
Run Code Online (Sandbox Code Playgroud)
这里我们findOneAndUpdate()在代码示例中有一个异步函数().如果没有错误(err)findOneAndUpdate()将被调用.因为这个函数是异步的,所以res.json(doc1)会立即调用它.假设没有错误findOneAndUpdate().将res.json(doc2)在else将被调用.现在已发送了两个响应,并且发生了无法设置标头错误消息.
在这种情况下,修复将是删除res.json(doc1).要将两个文档发送回客户端,res.json()可以将其写为res.json({ article: doc1, user: doc2 }).
ran*_*ess 15
我在这个问题上沸腾了头脑,因为处理回调时出现了一个粗心的错误.非返回的回调导致响应被设置两次.
我的程序有一个验证请求和查询数据库的代码.在验证错误是否存在之后,我正在使用验证错误回调index.js.如果验证通过它继续并成功/失败击中数据库.
var error = validateRequestDetails("create",queryReq);
if (error)
callback(error, null);
else
some code
callback(null, success);
Run Code Online (Sandbox Code Playgroud)
发生的事情是:Incase验证无法调用callback并设置响应.但没有回来.所以它仍然继续该方法转到db并命中成功/失败.它再次调用相同的回调,导致响应现在设置两次.
所以解决方案很简单,你需要'返回'回调,这样一旦发生错误,方法就不会继续执行,因此设置响应对象一次
var error = validateRequestDetails("create",queryReq);
if (error)
callback(error, null);
return;
else
some code
callback(null, success);
Run Code Online (Sandbox Code Playgroud)
Tro*_*jan 13
发送响应后传递语句时会出现此类错误.
例如:
res.send("something response");
console.log("jhgfjhgsdhgfsdf");
console.log("sdgsdfhdgfdhgsdf");
res.send("sopmething response");
Run Code Online (Sandbox Code Playgroud)
将导致您看到的错误,因为一旦发送了响应,res.send将不会执行以下操作.
如果你想做任何事情,你应该在发送回复之前做.
nag*_*han 11
在 RND 后自行查找错误:
1)我的错误代码:
return res.sendStatus(200).json({ data: result });
2)我的成功代码
return res.status(200).json({ data: result });
不同之处在于我使用了sendStatus()而不是status()。
当您发送 2 个响应时会发生此错误。例如 :
if(condition A)
{
res.render('Profile', {client:client_});
}
if (condition B){
res.render('Profile', {client:client_});
}
}
Run Code Online (Sandbox Code Playgroud)
想象一下,如果由于某种原因条件 A 和 B 为真,那么在第二个render你会得到那个错误
res.send()请检查您的代码是否为单个请求返回多个语句。就像我遇到这个问题的时候一样......
我的 Restify 节点应用程序中出现了这个问题。错误在于
switch (status) {
case -1:
res.send(400);
case 0:
res.send(200);
default:
res.send(500);
}
Run Code Online (Sandbox Code Playgroud)
我正在使用 switch 处理各种情况,而无需编写中断。对于那些不太熟悉 switch case 的人来说,知道没有 break、return 关键字。无论如何,case 下的代码及其下一行都将被执行。因此,即使我想发送 single res.send,由于这个错误,它返回了多个res.send语句,这提示
错误:将标头发送到客户端后无法设置标头。
res.send()通过在每个方法之前添加此或使用 return 解决了这个问题,例如return res.send(200)
switch (status) {
case -1:
res.send(400);
break;
case 0:
res.send(200);
break;
default:
res.send(500);
break;
}
Run Code Online (Sandbox Code Playgroud)
有时在res.end或res.send之后尝试调用next()函数时可能会出现此错误,如果在函数中res.send或res.end之后有next(),则尝试删除.注意:这里next()表示在使用您的响应(即res.send或res.end)响应客户端之后,您仍在尝试执行某些代码以再次响应,因此它不合法.
示例:
router.get('/',function (req,res,next){
res.send("request received");
next(); // this will give you the above exception
});
Run Code Online (Sandbox Code Playgroud)
next()从上面删除功能,它将工作.
如果使用回调函数,请return在该err块之后使用。这是可能发生此错误的方案之一。
userModel.createUser(data, function(err, data) {
if(err) {
res.status = 422
res.json(err)
return // without this return the error can happen.
}
return res.json(data)
})
Run Code Online (Sandbox Code Playgroud)
在Node版本上测试v10.16.0并表示4.16.4
就我而言,是 304 响应(缓存)导致了问题。
最简单的解决方案:
app.disable('etag');
Run Code Online (Sandbox Code Playgroud)
如果你想要更多的控制,这里的替代解决方案:
对于任何来到这里并且其他解决方案都没有帮助的人,在我的情况下,这体现在处理图像上传但不处理超时的路由上,因此如果上传时间过长且超时,则在触发回调时发送超时响应后,调用 res.send() 会导致崩溃,因为标头已经设置为考虑超时。
这很容易通过设置一个非常短的超时时间并使用相当大的图像击中路线来轻松重现,每次都会重现崩溃。
请搜索您的 app.get 中是否在 res.send("your result"); 之前未设置状态
我刚刚删除:
res.sendStatus(200);
Run Code Online (Sandbox Code Playgroud)
然后响应就起作用了!
res.send("your result");
Run Code Online (Sandbox Code Playgroud)
较新版本的 Node 支持res.headersSent布尔表达式。您可以使用它来验证您是否已经发送了回复:
if (!res.headersSent) // if doesn't sent yet
res.status(200).send({ "message": "This is a message" })
Run Code Online (Sandbox Code Playgroud)
笔记!虽然这有效并回答了问题,但这不是解决问题的正确方法,并且不推荐!
多次发送响应表明您的代码中存在需要修复的问题(这与在函数中依次使用两个 return 语句相同。这是一个错误)。
| 归档时间: |
|
| 查看次数: |
758735 次 |
| 最近记录: |