Erro: não é possível definir cabeçalhos depois de serem enviados ao cliente

724

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?

DjangoRocks
fonte
resposta simples de visionmedia: github.com/visionmedia/express/issues/634
shi11i 30/11/11
2
Google enviou-me a esta pergunta, mas versões mais recentes do ExpressJS tem res.headersSent booleano que pode ser usado para verificar se seguro definir cabeçalhos / Enviar
Julian Soro

Respostas:

1112

O resobjeto no Express é uma subclasse do Node.jshttp.ServerResponse ( leia a fonte http.js ). Você pode ligar res.setHeader(name, value)quantas vezes quiser até ligar res.writeHead(statusCode). Depois writeHead, os cabeçalhos são inseridos e você só pode ligar res.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 real function(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.js setHeaderlanç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 :

  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]) (Apenas Express)
  7. res.charset = 'utf-8' (Somente Express; afeta apenas métodos específicos do Express)
  8. res.contentType(type) (Apenas Express)

A resposta deve estar na cabeça e se torna corpo :

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

A resposta pode estar na Cabeça / Corpo e permanecer no Corpo :

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

A resposta pode estar na Cabeça / Corpo e fica Concluída :

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

A resposta pode estar em Cabeça / Corpo e permanece em seu estado atual:

  1. res.addTrailers(headers)

A resposta deve estar na cabeça e torna-se concluída :

  1. return next([err]) (Apenas Connect / Express)
  2. Qualquer exceção no middleware function(req, res, next) (somente Connect / Express)
  3. res.send(body|status[, headers|status[, status]]) (Apenas Express)
  4. res.attachment(filename) (Apenas Express)
  5. res.sendfile(path[, options[, callback]]) (Apenas Express)
  6. res.json(obj[, headers|status[, status]]) (Apenas Express)
  7. res.redirect(url[, status]) (Apenas Express)
  8. res.cookie(name, val[, options]) (Apenas Express)
  9. res.clearCookie(name[, options]) (Apenas Express)
  10. res.render(view[, options[, fn]]) (Apenas Express)
  11. res.partial(view[, options]) (Apenas Express)
yonran
fonte
13
Sim, verifique se chama next () ou outro cb duas vezes.
Tony Gutierrez
3
Ligações expressas parece morto
Korhan Ozturk
25
Também observe este erro clássico: res.redirect () não interrompe a execução da instrução ... então retorne depois. Caso contrário, outro código poderia ser executado, o que poderia causar, sem querer, o famoso erro de cabeçalho. Thanx pela explicação!
precisa saber é o seguinte
Geralmente é uma boa idéia para retorno uso no final de seu retorno para evitar isso
thethakuri
4
Cometi um erro muito pequeno no meu middleware, não o fiz returnantes next(), graças a isso me indicou o erro!
illcrx
113

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.usemétodo, você está anexando itens ao Server.prototype.stackem connect (pelo menos com a corrente npm 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étodo

O 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 o Server.prototype.handlemétodo principal for concluído, ele perceberá aquele:

  1. não há mais itens na pilha e / ou
  2. isso response.headerSenté verdade

Então, lança um erro. Mas o erro que gera é apenas esta resposta básica (do http.jscódigo-fonte de conexão :

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

Bem ali, está chamando res.setHeader('Content-Type', 'text/plain');, que você provavelmente configurou em seu rendermétodo, sem chamar response.end () , algo como:

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

A maneira como tudo precisa ser estruturado é assim:

Good Middleware

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

Middleware problemático

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

O middleware problemático define o cabeçalho da resposta sem efetuar response.end()chamadas next(), o que confunde o servidor do connect.

Lance Pollard
fonte
7
+1 Esta é uma ótima explicação, mas e o caso quando você usa res.redirect ()? Eu frequentemente encontro esse problema quando o middleware está tentando redirecionar com base em alguma condição. O middleware não deve redirecionar, de acordo com o exemplo "Good Middleware"?
Qodeninja 6/12/12
Você sabe que tenho esse problema exato devido ao que você chama de middleware problemático; no entanto, preciso de um caso em que eu retorne uma resposta, mas gostaria de fazer um processamento adicional em um controlador separado como parte da cadeia. Como faço para suprimir esse erro ?
QI.
57

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:

Erro: não é possível definir os cabeçalhos após o envio.

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:

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

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:

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

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 iffilial 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:

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

ou retornando quando a resposta é enviada:

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

Um grande pecador são funções assíncronas. Pegue a função desta pergunta, por exemplo:

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

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 erros findOneAndUpdate(). O res.json(doc2)no elseserá 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, o res.json()no else poderia ser escrito como res.json({ article: doc1, user: doc2 }).

Mika Sundland
fonte
2
Você está dentro de uma função assíncrona, e deve return ores.json
Genovo
Meu problema foi usando o res.sendloop for.
Maihan Nijat
1
Isso me ajudou no fim de entender e corrigir o problema, Muito obrigado :)
Pankaj Parkar
muito obrigado você economiza meu tempo.
Mohammad Faisal
Esta é definitivamente a melhor resposta!
Juanma Menendez
53

Eu tive esse mesmo problema e percebi que era porque estava ligando res.redirectsem uma returndeclaração, então a nextfunção também estava sendo chamada imediatamente depois:

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

O que deveria ter sido:

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

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 ligue app.usediretamente 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.

Peter Lyons
fonte
Um redirecionamento 30X é um código de resposta HTTP. w3.org/Protocols/rfc2616/rfc2616-sec10.html Os códigos 300-399 são diferentes variações de redirecionamento, com 302 e 301 sendo comumente usados ​​para enviar o cliente para um URL alternativo. Quando você faz response.redirect (...) no nó, um cabeçalho de redirecionamento 30X será enviado na resposta.
Peter Lyons
3
Ohhhh. Eu estava imaginando 30 redirecionamentos em uma linha ou algo
Janac Meena
17

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.

    var error = validateRequestDetails("create",queryReq);
    if (error)
        callback(error, null);
   else
    some code 
    callback(null, success);

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

  var error = validateRequestDetails("create",queryReq);
    if (error)
        callback(error, null);
        return;
    else
       some code 
       callback(null, success);
aleatoriedade
fonte
1
Obrigado! Este acabou por ser o meu problema também. Apenas fiz um ctrl + f e encontrei um callback(...)sem um return;depois dele, o que acabou causando o res.send(...)chamado duas vezes.
15

Esse tipo de erro será exibido quando você passar instruções após enviar uma resposta.

Por exemplo:

res.send("something response");
console.log("jhgfjhgsdhgfsdf");
console.log("sdgsdfhdgfdhgsdf");
res.send("sopmething response");

Irá resultar no erro que você está vendo, porque depois que a resposta for enviada, o seguinte res.sendnão será executado.

Se você quiser fazer alguma coisa, deve fazê-lo antes de enviar a resposta.

Trojan
fonte
Este foi o meu problema exato :)
Joel Balmer
6

À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:

router.get('/',function (req,res,next){
     res.send("request received");
     next(); // this will give you the above exception 
});

remova next()da função acima e funcionará.

Surendra Parchuru
fonte
6

Se você estiver usando funções de retorno de chamada, use returnapós o errbloco. Este é um dos cenários em que esse erro pode ocorrer.

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

Testado na versão do nó v10.16.0e expresso4.16.4

Krishnadas PC
fonte
4

Este erro ocorre quando você envia 2 respostas. Por exemplo :

if(condition A)
{ 

      res.render('Profile', {client:client_});

}

if (condition B){

      res.render('Profile', {client:client_});
    }
  }

Imagine se, por algum motivo, as condições A e B forem verdadeiras, no segundo rendervocê receberá esse erro

Badr Bellaj
fonte
3

No meu caso, foi uma resposta 304 (cache) que estava causando o problema.

Solução mais fácil:

app.disable('etag');

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/

blended
fonte
No meu caso, também resposta 304. Estou usando fibras para processamento. De qualquer forma, sua resposta ajuda muito. obrigado
Dileep stanley
Alguém pode explicar quais são as implicações para remover o cabeçalho etag?
mattwilsn
2
ETags permitem que o servidor não envie conteúdo que não foi alterado. Desligá-lo desativa esse recurso. A entrada da wikipedia ETag ( en.wikipedia.org/wiki/HTTP_ETag ) possui uma explicação mais longa.
blended
3

No meu caso, isso aconteceu com o React e o postal.js quando não cancelei a inscrição de um canal no componentWillUnmountretorno de chamada do meu componente React.

Zoltán
fonte
2

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.

Mike
fonte
1
como você lidou com o tempo limite para evitar isso?
2

Apenas inclinei isso. Você pode passar as respostas através desta função:

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();
});
Adam Boostani
fonte
2

Adicione este middlware e ele funcionará

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();
});
ASHISH RANJAN
fonte
2

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.

Ankit Manchanda
fonte
1

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.

rharding
fonte
como exatamente você resolveu isso? Eu tenho o mesmo problema com promessas. Eu não posso evitar aninhar-los ... então como faço para parar a execução na declaração de retorno?
saurabh 23/03
1

Vim aqui do nuxt , o problema estava no asyncDatamétodo do componente , esqueci de returnprometer que estava buscando dados e definindo o cabeçalho lá.

Nick Synev
fonte
1

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

erro não pode definir cabeçalhos após serem enviados ao cliente. Que foi resolvido adicionando isso ou usando return antes de cada método res.send () como return res.send (200)

switch (status) { case -1: res.send(400); break; case 0: res.send(200); break; default: res.send(500); break; }

KNDheeraj
fonte
obrigado por sua inspiração mesmo aconteceu comigo. Eu também resolvi com outra condição se.
Amr AbdelRahman 23/03
1

É 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.

Naved Ahmad
fonte
1

Simplesmente adiciono a palavra-chave de retorno como: return res.redirect("/great");e walla!

Emmanuel Benson
fonte
1

Eu tive o mesmo problema que foi causado pelo mangusto.

para corrigir o que você deve ativar Promises, para adicionar: mongoose.Promise = global.Promiseao seu código, que permite o usonative js promises .

outras alternativas para essa solução são:

var mongoose = require('mongoose');
// set Promise provider to bluebird
mongoose.Promise = require('bluebird');

e

// q
mongoose.Promise = require('q').Promise;

mas você precisa instalar esses pacotes primeiro.

sina
fonte
1

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 () .

nagender pratap chauhan
fonte
0

No texto datilografado, meu problema era que eu não fechei a conexão do websocket após receber uma mensagem.

WebSocket.on("message", (data) => {
    receivedMessage = true;
    doSomething(data);
    localSocket.close(); //This close the connection, allowing 
});
Janac Meena
fonte
0

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. `

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

`na chamada acima next () duas vezes gerará um erro

  1. 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

Sanjay
fonte
0

No meu caso, isso ocorre devido a vários retornos de chamada. Chamei o next()método várias vezes durante o código

Mr. Ratnadeep
fonte
0

Meu problema foi que eu tinha uma setIntervalcorrida, que tinha um if/elsebloco, onde o clearIntervalmétodo estava dentro do else:

      const dataExistsInterval = setInterval(async () => {
        const dataExists = Object.keys(req.body).length !== 0;
        if (dataExists) {
          if (!req.files.length) {
            return res.json({ msg: false });
          } else {
              clearInterval(dataExistsInterval);
            try {
            . . .

Colocar o clearIntervalantes do if/elsefez o truque.

Mike K
fonte
0

No meu caso, em um loop, eu coloquei res.render()isso pode ter sido tentado chamar várias vezes.

Hasan Sefa Ozalp
fonte
-1

Tudo o que eu tinha que fazer em caso desse erro era res.end ().

 auth.annonymousOnly = function(req, res, next) {
 // add other task here   
   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.

 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 
};
codificador
fonte