오류: 클라이언트에 보낸 후 헤더를 설정할 수 없습니다.

Node.js는 처음이라 문제가 좀 있습니다.

Node.js 4.10 및 Express 2.4.3을 사용하고 있습니다.

http://127.0.1:8888/auth/facebook에 접속하려고 하면 http://127.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) 

다음은 내 코드입니다.

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

제 코드에 무슨 문제가 있는지 알 수 있을까요?



질문에 대한 답변



resExpress의 오브젝트는 Node.js의 서브클래스입니다(http.js 소스를 읽습니다).전화할 수 있습니다.res.setHeader(name, value)전화할 때까지 얼마든지res.writeHead(statusCode).끝나고writeHead헤더는 로 작성되어 있으며, 콜만 할 수 있습니다.res.write(data)마지막으로res.end(data).

에러:보낸 후 헤더를 설정할 수 없습니다.”는 사용자가 이미 본문 또는 완료 상태이지만 일부 함수가 헤더 또는 상태 코드를 설정하려고 시도했음을 의미합니다.이 에러가 발생했을 경우는, 본문의 일부가 이미 기입된 후에 헤더를 송신하려고 하는 것을 찾아 주세요.예를 들어 실수로 두 번 호출된 콜백이나 본문이 전송된 후 발생한 오류를 찾습니다.

당신의 경우, 당신이 전화했습니다.res.redirect()이로 인해 응답이 Finished가 되었습니다.그러면 코드가 오류를 발생시킵니다.res.reqnull이 에러는, 실제의 에러내에서 발생했기 때문에,function(req, res, next)(콜백 내가 아님) Connect가 콜백을 검출하여 500 에러 페이지를 송신하려고 했습니다.그러나 헤더는 이미 전송되었기 때문에 Node.js의setHeader당신이 본 오류를 던졌습니다.

Node.js/Express 응답 메서드 및 호출해야 하는 타이밍의 포괄적인 목록:

응답은 선두에 있어야 하며 선두에 남아 있어야 합니다.

  1. res.writeContinue()
  2. res.statusCode = 404
  3. res.setHeader(name, value)
  4. res.getHeader(name)
  5. res.removeHeader(name)
  6. res.header(key[, val]) (익스프레스만)
  7. res.charset = 'utf-8'(Express 전용, Express 고유의 메서드에만 영향을 줍니다)
  8. res.contentType(type) (익스프레스만)

응답은 머리에 있어야 하며 본문이 됩니다.

  1. res.writeHead(statusCode, [reasonPhrase], [headers])

응답은 머리/몸통하나에 있을 수 있으며 본문에 남습니다.

  1. res.write(chunk, encoding='utf8')

응답은 Head/Body에 있을 수 있으며 Finished가 됩니다.

  1. res.end([data], [encoding])

응답은 Head/Body 중 하나일 수 있으며 현재 상태를 유지합니다.

  1. res.addTrailers(headers)

응답은 Head에 있어야 하며 Finished가 됩니다.

  1. return next([err])(접속/익스프레스만)
  2. 미들웨어 내의 예외function(req, res, next)(접속/익스프레스만)
  3. res.send(body status[, headers status[, status]]) (익스프레스만)
  4. res.attachment(filename) (익스프레스만)
  5. res.sendfile(path[, options[, callback]]) (익스프레스만)
  6. res.json(obj[, headers status[, status]]) (익스프레스만)
  7. res.redirect(url[, status]) (익스프레스만)
  8. res.cookie(name, val[, options]) (익스프레스만)
  9. res.clearCookie(name[, options]) (익스프레스만)
  10. res.render(view[, options[, fn]]) (익스프레스만)
  11. res.partial(view[, options]) (익스프레스만)



이 Q&A의 답변 중 일부는 틀렸습니다.받아들여진 답변도 실용적이지 않기 때문에 알기 쉬운 답변을 투고하고 싶습니다.제 답변에는 반복적으로 게시된 오류의 99%가 포함됩니다.에러의 실제의 이유에 대해서는, 인정된 답변을 참조해 주세요.


HTTP는 요청당 1개의 응답이 필요한 사이클을 사용합니다.클라이언트가 요구(POST 또는 GET 등)를 송신하면, 서버는 1개의 응답만 송신합니다.

다음 오류 메시지:

오류: 헤더를 보낸 후에는 헤더를 설정할 수 없습니다.

보통 1개의 요청에 대해 여러 개의 응답을 보낼 때 발생합니다.다음 함수가 요청당1회만 호출되는지 확인합니다.

  • 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' }); } 

POST 요구가 /api/route1로 전송되면 콜백 내의 모든 회선이 실행됩니다.A Cannot set headers after that sended 오류 메시지가 표시되는 이유는 다음과 같습니다.res.json()는 2회 호출됩니다.즉, 2개의 응답이 송신됩니다.

요청당 하나의 응답만 보낼 수 있습니다!


위의 코드 샘플의 오류는 명백했습니다.보다 일반적인 문제는 브런치가 여러 개 있는 경우입니다.

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

콜백이 연결된 이 루트는 데이터베이스 내의 회사를 찾습니다.존재하지 않는 회사에 대한 쿼리를 수행할 경우else if분기하여 404 응답을 보냅니다.그 후, 회답도 보내는 다음 스테이트먼트로 넘어갑니다.이제 두 개의 응답을 보냈고 오류 메시지가 나타납니다.이 코드를 수정하려면 응답을 1개만 보냅니다.

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

또는 응답 전송 시 반환:

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

큰 죄인은 비동기 함수입니다.이 질문의 함수를 예로 들어 보겠습니다.

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

여기에는 비동기 함수가 있습니다.findOneAndUpdate())를 참조해 주세요.에러가 없는 경우(err)findOneAndUpdate()호출됩니다.이 함수는 비동기이기 때문에res.json(doc1)즉시 호출됩니다.에 오류가 없다고 가정합니다.findOneAndUpdate().그res.json(doc2)에서else그러면 호출됩니다.이제 두 개의 응답이 전송되었으며 “헤더를 설정할 수 없습니다” 오류 메시지가 나타납니다.

이 경우 수정은 다음 명령어를 삭제하는 것입니다.res.json(doc1)양쪽 문서를 클라이언트에 반송하려면res.json()다른 말로 하면, 라고 할 수 있다.res.json({ article: doc1, user: doc2 }).




나도 한동안 이 오류가 있었어.(희망) 머리를 싸매서 여기에 참고용으로 쓰고 싶었던 것 같아요.

접속 또는 표현에 미들웨어를 추가하는 경우(접속 상에 구축되어 있음)에는app.use메서드, 아이템을 추가합니다.Server.prototype.stack(적어도 조류와) 연결해서npm install connect(이 게시물에서의 github와는 상당히 다른 모습)서버가 요구를 수신하면, 스택상에서 반복해, 콜 합니다.(request, response, next)방법.

문제는 미들웨어 항목 중 하나가 응답 본문 또는 헤더에 쓰이지만(어떤 이유로든) 호출하지 않고 핵심으로 호출하는 경우입니다.Server.prototype.handle메서드가 완료되면 다음 사항을 알 수 있습니다.

  1. 스택에 더 이상 항목이 없습니다.
  2. 그거response.headerSent정말이에요.

그래서 오류가 발생합니다.단, 이 에러는 (접속으로부터의) 기본적인 응답에 불과합니다.http.js소스 코드:

res.statusCode = 404; res.setHeader('Content-Type', 'text/plain'); res.end('Cannot ' + req.method + ' ' + req.url); 

바로 저기, 전화벨이 울리고 있어res.setHeader('Content-Type', 'text/plain');에 설정되어 있을 가능성이 있습니다.rendermethod, 호출 응답 없음.end는 다음과 같습니다.

response.setHeader("Content-Type", "text/html"); response.write("<p>Hello World</p>"); 

모든 것을 구조화해야 하는 방법은 다음과 같습니다.

뛰어난 미들웨어

// 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); 

문제가 있는 미들웨어

var problemMiddleware = function(request, response, next) {
response.setHeader("Content-Type", "text/html");
response.write("<p>Hello World</p>");
next(); }; 

문제가 있는 미들웨어는 호출하지 않고 응답 헤더를 설정합니다.response.end()및 콜next()(접속 서버를 혼란스럽게 합니다).




저도 같은 문제가 있었는데 제가 전화했었기 때문에res.redirect없이return스테이트먼트, 그러니까next그 직후에 함수도 호출되었습니다.

auth.annonymousOnly = function(req, res, next) {
if (req.user) res.redirect('/');
next(); }; 

다음 중 어느 것이어야 합니까?

auth.annonymousOnly = function(req, res, next) {
if (req.user) return res.redirect('/');
next(); }; 



많은 사람들이 이 오류를 경험합니다.이것은 비동기 처리와 혼동됩니다.코드 중 일부는 첫 번째 틱에서 헤더를 설정하고 다음 틱에서 비동기 콜백을 실행하고 있을 가능성이 높습니다.그 사이에 응답 헤더가 송신됩니다만, 그 후(30X 리다이렉트등) 이후의 헤더가 추가의 헤더를 추가하려고 합니다만, 응답 헤더가 이미 송신되었기 때문에, 너무 늦습니다.

오류의 원인이 무엇인지 정확히 알 수 없지만, 조사해야 할 잠재적인 영역으로 콜백을 살펴보십시오.

코드를 심플하게 하기 위한 간단한 힌트.제거하다app.configure()전화만 하면 돼app.use최고 수준의 범위로 직접 이동할 수 있습니다.

Facebook 및 기타 서드파티 인증 프로바이더를 실행하는 everyauth 모듈도 참조하십시오.