Sou relativamente novo no Node.js e estou com alguns problemas.
Estou usando o Node.js. 4.10 e o Express 2.4.3.
Quando tento acessar http://127.0.0.1:8888/auth/facebook , sou redirecionado para http://127.0.0.1:8888/auth/facebook_callback .
Eu recebi o seguinte erro:
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)
O seguinte é o meu código:
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);
Posso saber o que há de errado com meu código?
javascript
node.js
express
DjangoRocks
fonte
fonte
Respostas:
O
res
objeto no Express é uma subclasse do Node.jshttp.ServerResponse
( leia a fonte http.js ). Você pode ligarres.setHeader(name, value)
quantas vezes quiser até ligarres.writeHead(statusCode)
. DepoiswriteHead
, os cabeçalhos são inseridos e você só pode ligarres.write(data)
e, finalmente,res.end(data)
.O erro "Erro: não é possível definir cabeçalhos após o envio". significa que você já está no estado Corpo ou Concluído, mas alguma função tentou definir um cabeçalho ou statusCode. Quando você vir esse erro, tente procurar por qualquer coisa que tente enviar um cabeçalho depois que parte do corpo já foi gravada. Por exemplo, procure retornos de chamada acidentalmente chamados duas vezes ou qualquer erro que ocorra após o envio do corpo.
No seu caso, você ligou
res.redirect()
, o que fez com que a resposta fosse concluída. Em seguida, seu código gerou um erro (res.req
énull
). e como o erro ocorreu dentro do seu realfunction(req, res, next)
(não dentro de um retorno de chamada), o Connect conseguiu capturá-lo e tentou enviar uma página de erro 500. Mas como os cabeçalhos já foram enviados, o Node.jssetHeader
lançou o erro que você viu.Lista abrangente de métodos de resposta Node.js / Express e quando eles devem ser chamados:
A resposta deve estar no Head e permanecer no Head :
res.writeContinue()
res.statusCode = 404
res.setHeader(name, value)
res.getHeader(name)
res.removeHeader(name)
res.header(key[, val])
(Apenas Express)res.charset = 'utf-8'
(Somente Express; afeta apenas métodos específicos do Express)res.contentType(type)
(Apenas Express)A resposta deve estar na cabeça e se torna corpo :
res.writeHead(statusCode, [reasonPhrase], [headers])
A resposta pode estar na Cabeça / Corpo e permanecer no Corpo :
res.write(chunk, encoding='utf8')
A resposta pode estar na Cabeça / Corpo e fica Concluída :
res.end([data], [encoding])
A resposta pode estar em Cabeça / Corpo e permanece em seu estado atual:
res.addTrailers(headers)
A resposta deve estar na cabeça e torna-se concluída :
return next([err])
(Apenas Connect / Express)function(req, res, next)
(somente Connect / Express)res.send(body|status[, headers|status[, status]])
(Apenas Express)res.attachment(filename)
(Apenas Express)res.sendfile(path[, options[, callback]])
(Apenas Express)res.json(obj[, headers|status[, status]])
(Apenas Express)res.redirect(url[, status])
(Apenas Express)res.cookie(name, val[, options])
(Apenas Express)res.clearCookie(name[, options])
(Apenas Express)res.render(view[, options[, fn]])
(Apenas Express)res.partial(view[, options])
(Apenas Express)fonte
return
antesnext()
, graças a isso me indicou o erro!Eu encontrei esse erro também por um tempo. Eu acho que (espero) eu envolvi minha cabeça em torno disso, queria escrever aqui para referência.
Quando você adiciona o middleware para conectar ou expressar (que é construído sobre a conexão) usando o
app.use
método, você está anexando itens aoServer.prototype.stack
em connect (pelo menos com a correntenpm install connect
, que parece bem diferente do github desta postagem). Quando o servidor recebe uma solicitação, ele itera sobre a pilha, chamando o(request, response, next)
métodoO problema é que, se um dos itens de middleware gravar no corpo ou nos cabeçalhos da resposta (parece que é por algum motivo), mas não chamar
response.end()
e você ligarnext()
então, à medida que oServer.prototype.handle
método principal for concluído, ele perceberá aquele:response.headerSent
é verdadeEntão, lança um erro. Mas o erro que gera é apenas esta resposta básica (do
http.js
código-fonte de conexão :Bem ali, está chamando
res.setHeader('Content-Type', 'text/plain');
, que você provavelmente configurou em seurender
método, sem chamar response.end () , algo como:A maneira como tudo precisa ser estruturado é assim:
Good Middleware
Middleware problemático
O middleware problemático define o cabeçalho da resposta sem efetuar
response.end()
chamadasnext()
, o que confunde o servidor do connect.fonte
Algumas das respostas nestas perguntas e respostas estão erradas. A resposta aceita também não é muito "prática", então quero postar uma resposta que explique as coisas em termos mais simples. Minha resposta cobrirá 99% dos erros que eu vejo postados repetidamente. Pelas razões reais por trás do erro, dê uma olhada na resposta aceita.
O HTTP usa um ciclo que requer uma resposta por solicitação. Quando o cliente envia uma solicitação (por exemplo, POST ou GET), o servidor deve enviar apenas uma resposta para ele.
Esta mensagem de erro:
geralmente acontece quando você envia várias respostas para uma solicitação. Verifique se as seguintes funções são chamadas apenas uma vez por solicitação:
res.json()
res.send()
res.redirect()
res.render()
(e mais alguns que raramente são usados, verifique a resposta aceita)
O retorno de chamada da rota não retornará quando essas funções res forem chamadas. Ele continuará em execução até atingir o final da função ou uma instrução de retorno. Se você quiser retornar ao enviar uma resposta que você pode fazê-lo assim:
return res.send()
.Tome por exemplo este código:
Quando uma solicitação POST é enviada para / api / route1, ela executa todas as linhas do retorno de chamada. A mensagem de erro Não é possível definir cabeçalhos após o envio será lançada porque
res.json()
é chamada duas vezes, o que significa que duas respostas são enviadas.Apenas uma resposta pode ser enviada por solicitação!
O erro no exemplo de código acima foi óbvio. Um problema mais típico é quando você tem várias ramificações:
Essa rota com retorno de chamada anexado localiza uma empresa em um banco de dados. Ao fazer uma consulta para uma empresa que não existe, entraremos na
else if
filial e enviaremos uma resposta 404. Depois disso, continuaremos com a próxima declaração, que também envia uma resposta. Agora, enviamos duas respostas e a mensagem de erro ocorrerá. Podemos corrigir esse código certificando-se de enviar apenas uma resposta:ou retornando quando a resposta é enviada:
Um grande pecador são funções assíncronas. Pegue a função desta pergunta, por exemplo:
Aqui temos uma função assíncrona (
findOneAndUpdate()
) no exemplo de código. Se não houver erros (err
)findOneAndUpdate()
serão chamados. Como essa função é assíncrona,res.json(doc1)
ela será chamada imediatamente. Suponha que não haja errosfindOneAndUpdate()
. Ores.json(doc2)
noelse
será então chamado. Duas respostas foram enviadas e o cabeçalho Não é possível definir os cabeçalhos mensagem de erro ocorre.A correção, nesse caso, seria remover o
res.json(doc1)
. Para enviar os dois documentos de volta ao cliente, ores.json()
no else poderia ser escrito comores.json({ article: doc1, user: doc2 })
.fonte
return
ores.json
res.send
loop for.Eu tive esse mesmo problema e percebi que era porque estava ligando
res.redirect
sem umareturn
declaração, então anext
função também estava sendo chamada imediatamente depois:O que deveria ter sido:
fonte
Muitas pessoas atingiram esse erro. Isso é confuso com o processamento assíncrono. Provavelmente, parte do seu código está definindo cabeçalhos no primeiro tick e, em seguida, você está executando um retorno de chamada assíncrona em um tick futuro. No meio, o cabeçalho da resposta é enviado, mas outros cabeçalhos (como um redirecionamento 30X) tentam adicionar cabeçalhos extras, mas é tarde demais, pois o cabeçalho da resposta já foi transmitido.
Não sei exatamente o que está causando o seu erro, mas observe todos os retornos de chamada como possíveis áreas a serem investigadas.
Uma dica fácil para simplificar seu código. Livre-se
app.configure()
e ligueapp.use
diretamente para o seu escopo de nível superior.Veja também o módulo everyauth , que possui o Facebook e uma dúzia de outros provedores de autenticação de terceiros.
fonte
Eu fervi minha cabeça sobre esse problema e isso aconteceu devido a um erro descuidado ao lidar com os retornos de chamada. retornos de chamada não retornados fazem com que a resposta seja definida duas vezes.
Meu programa tinha um código que valida a solicitação e consulta o banco de dados. depois de validar se há algum erro, eu estava retornando o index.js com os erros de validação. E se a validação for aprovada, ela avança e atinge o banco de dados com êxito / falha.
O que estava acontecendo é: Falha na validação do caso, o retorno de chamada é chamado e a resposta é definida. Mas não retornou. Por isso, continua o método indo para db e atingindo o sucesso / falha. Ele chama o mesmo retorno de chamada novamente, fazendo com que a resposta seja definida duas vezes agora.
Portanto, a solução é simples, você precisa 'retornar' o retorno de chamada para que o método não continue executando, uma vez que o erro ocorreu e, portanto, defina o objeto de resposta uma vez
fonte
callback(...)
sem umreturn;
depois dele, o que acabou causando ores.send(...)
chamado duas vezes.Esse tipo de erro será exibido quando você passar instruções após enviar uma resposta.
Por exemplo:
Irá resultar no erro que você está vendo, porque depois que a resposta for enviada, o seguinte
res.send
não será executado.Se você quiser fazer alguma coisa, deve fazê-lo antes de enviar a resposta.
fonte
Às vezes, você pode receber esse erro ao tentar chamar a função next () após res.end ou res.send , tente excluir se tiver a próxima () após res.send ou res.end em sua função. Nota: aqui next () significa que depois de responder ao cliente com sua resposta (por exemplo, res.send ou res.end ) você ainda está tentando executar algum código para responder novamente, para que não seja legal.
Exemplo:
fonte
Se você estiver usando funções de retorno de chamada, use
return
após oerr
bloco. Este é um dos cenários em que esse erro pode ocorrer.Testado na versão do nó
v10.16.0
e expresso4.16.4
fonte
Este erro ocorre quando você envia 2 respostas. Por exemplo :
Imagine se, por algum motivo, as condições A e B forem verdadeiras, no segundo
render
você receberá esse errofonte
No meu caso, foi uma resposta 304 (cache) que estava causando o problema.
Solução mais fácil:
Solução alternativa aqui, se você quiser mais controle:
http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/
fonte
No meu caso, isso aconteceu com o React e o postal.js quando não cancelei a inscrição de um canal no
componentWillUnmount
retorno de chamada do meu componente React.fonte
Para quem está chegando a isso e nenhuma das outras soluções ajudou, no meu caso, isso se manifestou em uma rota que manipulava o upload de imagens, mas não tratava de tempos limite , e, portanto, se o upload demorasse muito e atingisse o tempo limite, quando o retorno de chamada foi acionado após o envio da resposta do tempo limite , a chamada de res.send () resultou na falha, pois os cabeçalhos já estavam definidos para contabilizar o tempo limite.
Isso foi reproduzido facilmente, definindo um tempo limite muito curto e atingindo a rota com uma imagem decentemente grande; o acidente foi reproduzido todas as vezes.
fonte
Apenas inclinei isso. Você pode passar as respostas através desta função:
fonte
Adicione este middlware e ele funcionará
fonte
Isso acontece quando a resposta foi entregue ao cliente e, novamente, você está tentando dar uma resposta. Você deve verificar no seu código se, em algum lugar, você está retornando a resposta ao cliente novamente, o que causa esse erro. Verifique e retorne a resposta uma vez quando desejar retornar.
fonte
Eu tive esse problema quando aninhava promessas. Uma promessa dentro de uma promessa retornaria 200 para o servidor, mas a declaração de captura da promessa externa retornaria 500. Depois que eu resolvia isso, o problema desaparecia.
fonte
Vim aqui do nuxt , o problema estava no
asyncData
método do componente , esqueci dereturn
prometer que estava buscando dados e definindo o cabeçalho lá.fonte
Verifique se o seu código está retornando várias instruções res.send () para uma única solicitação. Como quando eu tive esse problema ....
Eu era esse problema no meu aplicativo de nó restify. O erro foi que
switch (status) { case -1: res.send(400); case 0: res.send(200); default: res.send(500); }
Eu estava lidando com vários casos usando o switch sem interrupção de gravação. Para aqueles pouco familiarizados com o caso de troca, saiba que, sem interrupção, retorne palavras-chave. O código em maiúsculas e minúsculas e as próximas linhas serão executados, não importa o quê. Portanto, mesmo que eu queira enviar um único res.send, devido a esse erro, ele estava retornando várias instruções res.send, o que solicitou
switch (status) { case -1: res.send(400); break; case 0: res.send(200); break; default: res.send(500); break; }
fonte
É muito provável que isso seja mais um nó, 99% das vezes é um retorno de chamada duplo, fazendo com que você responda duas vezes, ou a próxima () duas vezes etc, com certeza. Resolveu que meu problema estava usando next () dentro de um loop. Remova o próximo () do loop ou pare de chamá-lo mais de uma vez.
fonte
Eu recebi um erro semelhante ao tentar enviar resposta dentro de uma função de loop. A solução simples foi mover o
fora do loop, pois você só pode enviar o cabeçalho de resposta uma vez.
https://www.tutorialspoint.com/nodejs/nodejs_response_object.htm
fonte
Simplesmente adiciono a palavra-chave de retorno como:
return res.redirect("/great");
e walla!fonte
Eu tive o mesmo problema que foi causado pelo mangusto.
para corrigir o que você deve ativar
Promises
, para adicionar:mongoose.Promise = global.Promise
ao seu código, que permite o usonative js promises
.outras alternativas para essa solução são:
e
mas você precisa instalar esses pacotes primeiro.
fonte
erro encontrado sozinho após um RND:
1) meu código de erro:
return res.sendStatus(200).json({ data: result });
2) meu código de sucesso
return res.status(200).json({ data: result });
a diferença é que eu usei sendStatus () em vez de status () .
fonte
No texto datilografado, meu problema era que eu não fechei a conexão do websocket após receber uma mensagem.
fonte
Se você não obteve ajuda de cima: para noobs A razão por trás desse erro está enviando uma solicitação várias vezes, vamos entender em alguns casos: - 1. `
`na chamada acima next () duas vezes gerará um erro
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);* }) })
aqui responder é enviar duas vezes verificar se você já enviou uma resposta
fonte
No meu caso, isso ocorre devido a vários retornos de chamada. Chamei o
next()
método várias vezes durante o códigofonte
Meu problema foi que eu tinha uma
setInterval
corrida, que tinha umif/else
bloco, onde oclearInterval
método estava dentro doelse
:Colocar o
clearInterval
antes doif/else
fez o truque.fonte
No meu caso, em um loop, eu coloquei
res.render()
isso pode ter sido tentado chamar várias vezes.fonte
Tudo o que eu tinha que fazer em caso desse erro era res.end ().
O outro problema que você pode estar enfrentando é que existe um código após res.json e res. Escreva. Nesse caso, você precisa usar return para interromper a execução depois disso.
fonte