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)
다음은 내 코드입니다.
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);
내 코드에 어떤 문제가 있는지 알 수 있습니까?
답변
res
Express 의 객체는 Node.js의http.ServerResponse
하위 클래스입니다 ( http.js 소스 읽기 ). 전화 res.setHeader(name, value)
할 때까지 원하는만큼 전화를 걸 수 res.writeHead(statusCode)
있습니다. 이후 writeHead
에는 헤더가 구워지고, 만 호출 할 수 res.write(data)
있으며 마지막으로res.end(data)
.
오류 : “오류 : 헤더를 보낸 후 설정할 수 없습니다.” 은 이미 본문 또는 완료 상태에 있지만 일부 함수가 헤더 또는 statusCode를 설정하려고 시도했음을 의미합니다. 이 오류가 표시되면 일부 본문이 이미 작성된 후 헤더를 보내려는 항목을 찾으십시오. 예를 들어 실수로 두 번 호출 된 콜백이나 본문이 전송 된 후 발생하는 오류를 찾으십시오.
귀하의 경우에 전화를 걸어 res.redirect()
응답이 완료되었습니다. 그런 다음 코드에서 오류가 발생했습니다 ( res.req
is null
). function(req, res, next)
콜백이 아닌 실제 내에서 오류가 발생했기 때문에 Connect는이 오류를 잡아 500 오류 페이지를 보내려고했습니다. 그러나 헤더가 이미 전송되었으므로 Node.js는setHeader
는 본 오류를 던졌습니다.
Node.js / Express 응답 메소드의 포괄적 인 목록 및 호출시기 :
응답에 있어야 헤드 및 유지 헤드 :
res.writeContinue()
res.statusCode = 404
res.setHeader(name, value)
res.getHeader(name)
res.removeHeader(name)
res.header(key[, val])
(익스프레스 만)res.charset = 'utf-8'
(Express 만 해당, Express 특정 방법에만 영향을 미침)res.contentType(type)
(익스프레스 만)
응답은 Head에 있어야하며 Body 가됩니다 .
응답 중 하나 일 수 있습니다 헤드 / 바디 와 남아 바디 :
응답 중 하나 일 수 있습니다 헤드 / 바디 및됩니다 완료 :
응답은 헤드 / 바디 일 수 있으며 현재 상태를 유지합니다.
응답에 있어야 헤드 및됩니다 완료 :
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])
(익스프레스 만)
답변
나는이 오류를 잠시 동안 만났다. 내 머리를 감아 서 여기에 참고로 쓰고 싶었다고 생각합니다.
메소드를 사용하여 연결 하거나 표현 하기 위해 (미리 연결되어있는) 미들웨어를 추가 할 때 연결에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);
거기에서 response.end ()를 호출하지 않고 메소드 res.setHeader('Content-Type', 'text/plain');
에서 설정했을 가능성이있는 을 호출합니다 .render
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()
connect의 서버를 혼란스럽게합니다.
답변
이 Q & A의 일부 답변이 잘못되었습니다. 허용되는 답변도 “실제적인”것은 아니므로 더 간단한 용어로 설명하는 답변을 게시하고 싶습니다. 내 대답은 반복해서 게시 된 오류의 99 %를 다룰 것입니다. 오류의 실제 원인으로 허용되는 답변을 살펴보십시오.
HTTP는 요청 당 하나의 응답이 필요한주기를 사용합니다. 클라이언트가 요청 (예 : POST 또는 GET)을 보내면 서버는 하나의 응답 만 다시 보내야합니다.
이 오류 메시지 :
오류 : 헤더를 보낸 후 설정할 수 없습니다.
일반적으로 한 요청에 여러 응답을 보낼 때 발생합니다. 다음 함수는 요청 당 한 번만 호출되어야합니다.
res.json()
res.send()
res.redirect()
res.render()
(그리고 거의 사용되지 않는 몇 가지, 허용되는 답변을 확인하십시오)
이러한 res 함수가 호출 될 때 경로 콜백은 반환되지 않습니다. 함수의 끝이나 return 문에 도달 할 때까지 계속 실행됩니다. 응답을 보낼 때 돌아 오려면 다음과 같이하십시오 : 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로 전송 되면 콜백의 모든 라인이 실행됩니다. 가 전송 된 후 캔은 헤더를 설정하지 때문에 오류 메시지가 발생합니다 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.
});
}
콜백이 첨부 된이 경로는 데이터베이스에서 회사를 찾습니다. 존재하지 않는 회사에 대한 쿼리를 수행하면 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);
}
});
또는 응답이 전송 될 때 돌아갑니다.
.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 })
.
답변
나는 똑같은 문제가 있었고 명령문 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 및 12 개 이상의 타사 인증 제공 업체를 수행 하는 everyauth 모듈 도 참조하십시오 .
답변
나는이 문제에 대해 머리를 끓 였고 콜백 처리에 대한 부주의 한 실수로 인해 발생했습니다. 반환되지 않은 콜백은 응답을 두 번 설정합니다.!
내 프로그램에는 요청을 확인하고 DB를 쿼리하는 코드가 있습니다. 오류가 있는지 확인한 후 유효성 검사 오류가있는 index.js를 다시 호출했습니다. 그리고 유효성 검사가 통과하면 성공 / 실패로 db에 도달합니다.
var error = validateRequestDetails("create",queryReq);
if (error)
callback(error, null);
else
some code
callback(null, success);
발생한 일 : 유효성 검사에 실패하면 콜백 호출 및 응답 설정이 실패합니다. 그러나 반환되지 않았습니다. 따라서 여전히 방법이 db로 이동하여 success / failure에 도달합니다. 동일한 콜백을 다시 호출하여 응답이 두 번 설정되었습니다.
따라서 해결책은 간단합니다. 오류가 발생하면 메소드가 계속 실행되지 않도록 콜백을 ‘반환’해야하므로 응답 객체를 한 번 설정해야합니다
var error = validateRequestDetails("create",queryReq);
if (error)
callback(error, null);
return;
else
some code
callback(null, success);
답변
응답을 보낸 후 명령문을 전달하면 이러한 유형의 오류가 발생합니다.
예를 들면 다음과 같습니다.
res.send("something response");
console.log("jhgfjhgsdhgfsdf");
console.log("sdgsdfhdgfdhgsdf");
res.send("sopmething response");
응답이 전송되면 다음 res.send
이 실행되지 않기 때문에보고있는 오류가 발생합니다 .
원하는 것을하려면 응답을 보내기 전에해야합니다.