Errore: impossibile impostare le intestazioni dopo che sono state inviate al client


725

Sono abbastanza nuovo su Node.js e ho dei problemi.

Sto usando Node.js 4.10 ed Express 2.4.3.

Quando provo ad accedere a http://127.0.0.1:8888/auth/facebook , verrò reindirizzato a http://127.0.0.1:8888/auth/facebook_callback .

Ho quindi ricevuto il seguente errore:

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)

Il seguente è il mio codice:

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 sapere cosa c'è che non va nel mio codice?


risposta semplice da visionmedia: github.com/visionmedia/express/issues/634
shi11i

2
Google mi ha inviato a questa domanda, ma le versioni più recenti di ExpressJS hanno res.headersInviato un valore booleano che può essere utilizzato per verificare se è possibile impostare / inviare le intestazioni in modo sicuro
Julian Soro,

Risposte:


1113

L' resoggetto in Express è una sottoclasse di Node.jshttp.ServerResponse ( leggi l'origine http.js ). Puoi chiamare tutte res.setHeader(name, value)le volte che vuoi fino a quando non chiami res.writeHead(statusCode). Dopo writeHead, le intestazioni sono cotti in e si può solo chiamare res.write(data), e alla fine res.end(data).

L'errore "Errore: impossibile impostare le intestazioni dopo l'invio." significa che sei già nello stato Corpo o Finito, ma alcune funzioni hanno tentato di impostare un'intestazione o statusCode. Quando viene visualizzato questo errore, prova a cercare qualsiasi cosa tenti di inviare un'intestazione dopo che è stato già scritto un po 'del corpo. Ad esempio, cercare callback richiamati accidentalmente due volte o qualsiasi errore che si verifica dopo l'invio del corpo.

Nel tuo caso, hai chiamato res.redirect(), facendo sì che la risposta diventasse Finita. Quindi il tuo codice ha generato un errore ( res.reqis null). e poiché l'errore si è verificato all'interno del tuo effettivo function(req, res, next)(non all'interno di una richiamata), Connect è stato in grado di rilevarlo e quindi ha tentato di inviare una pagina di errore 500. Ma dal momento che le intestazioni erano già state inviate, Node.js ha setHeaderlanciato l'errore che hai visto.

Elenco completo dei metodi di risposta Node.js / Express e quando devono essere chiamati:

La risposta deve essere in testa e rimane in testa :

  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]) (Solo espresso)
  7. res.charset = 'utf-8' (Solo Express; influisce solo sui metodi specifici di Express)
  8. res.contentType(type) (Solo espresso)

La risposta deve essere in testa e diventa Corpo :

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

La risposta può essere in Testa / Corpo e rimane in Corpo :

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

La risposta può essere in una delle due teste / corpo e diventa Finita :

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

La risposta può essere in una delle due teste / corpo e rimane nel suo stato attuale:

  1. res.addTrailers(headers)

La risposta deve essere in testa e diventa Finita :

  1. return next([err]) (Solo Connect / Express)
  2. Eventuali eccezioni nel middleware function(req, res, next)(solo Connect / Express)
  3. res.send(body|status[, headers|status[, status]]) (Solo espresso)
  4. res.attachment(filename) (Solo espresso)
  5. res.sendfile(path[, options[, callback]]) (Solo espresso)
  6. res.json(obj[, headers|status[, status]]) (Solo espresso)
  7. res.redirect(url[, status]) (Solo espresso)
  8. res.cookie(name, val[, options]) (Solo espresso)
  9. res.clearCookie(name[, options]) (Solo espresso)
  10. res.render(view[, options[, fn]]) (Solo espresso)
  11. res.partial(view[, options]) (Solo espresso)

13
Sì, controlla per chiamare next () o altri cb due volte.
Tony Gutierrez,

3
I collegamenti espressi sembrano morti
Korhan Ozturk il

25
fai attenzione anche a questo classico errore: res.redirect () non ferma l'esecuzione dell'istruzione ... quindi torna dopo. Altrimenti potrebbe essere eseguito altro codice che potrebbe causare involontariamente il famoso errore di intestazione. Grazie per la spiegazione!
KLoozen,

Di solito è una buona idea usare return alla fine del callback per evitarlo
thethakuri

4
Ho fatto un piccolo errore nel mio middleware, non l'ho mai fatto returnprima next(), grazie questo mi ha indicato l'errore!
illcrx,

113

Ho riscontrato questo errore anche per un po '. Penso (spero) di averlo avvolto, volevo scriverlo qui come riferimento.

Quando aggiungi middleware per connetterti o esprimere (che si basa su connect) usando il app.usemetodo, stai aggiungendo elementi a Server.prototype.stackin connect (almeno con l'attuale npm install connect, che sembra abbastanza diverso da quello github a partire da questo post). Quando il server riceve una richiesta, scorre nello stack, chiamando il (request, response, next)metodo.

Il problema è che se uno degli elementi del middleware scrive nel corpo della risposta o nelle intestazioni (sembra che sia o / o per qualche motivo), ma non chiama response.end()e tu chiaminext() quando il Server.prototype.handlemetodo principale viene completato, noterà quello:

  1. non ci sono più oggetti nella pila e / o
  2. questo response.headerSentè vero.

Quindi, genera un errore. Ma l'errore che genera è proprio questa risposta di base (dal http.jscodice sorgente di connessione :

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

Proprio lì, sta chiamando res.setHeader('Content-Type', 'text/plain');, che probabilmente avrai impostato nel tuo rendermetodo, senza chiamare response.end () , qualcosa del tipo:

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

Il modo in cui tutto deve essere strutturato è così:

Buon 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 problematico

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

Il middleware problematico imposta l'intestazione della risposta senza chiamare response.end()e chiamare next(), il che confonde il server di connect.


7
+1 Questa è un'ottima spiegazione, ma per quanto riguarda il caso in cui si utilizza res.redirect ()? Mi capita spesso di riscontrare questo problema quando il middleware sta cercando di reindirizzare in base a una condizione. Il middleware non dovrebbe reindirizzare, secondo il tuo esempio "Good Middleware"?
qodeninja,

Sai che ho questo esatto problema a causa di quello che chiami un middleware problematico, tuttavia ho bisogno di un caso in cui restituisco la risposta ma vorrei fare un'ulteriore elaborazione in un controller separato come parte della catena, come posso fare per eliminare questo errore ?
iQ.

57

Alcune delle risposte in queste domande e risposte sono errate. Anche la risposta accettata non è molto "pratica", quindi voglio pubblicare una risposta che spieghi le cose in termini più semplici. La mia risposta coprirà il 99% degli errori che vedo pubblicati più e più volte. Per i motivi reali dietro l'errore, dai un'occhiata alla risposta accettata.


HTTP utilizza un ciclo che richiede una risposta per richiesta. Quando il client invia una richiesta (ad es. POST o GET), il server deve inviare una sola risposta.

Questo messaggio di errore:

Errore: impossibile impostare le intestazioni dopo l'invio.

di solito accade quando si inviano più risposte per una richiesta. Assicurarsi che le seguenti funzioni vengano chiamate una sola volta per richiesta:

  • res.json()
  • res.send()
  • res.redirect()
  • res.render()

(e pochi altri che vengono usati raramente, controlla la risposta accettata)

Il callback del percorso non ritornerà quando vengono chiamate queste funzioni di res. Continuerà a funzionare fino a quando non raggiunge la fine della funzione o un'istruzione return. Se si desidera restituire l'invio di una risposta si può fare in questo modo: return res.send().


Prendi ad esempio questo codice:

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 una richiesta POST viene inviata a / api / route1 , verrà eseguita ogni linea nel callback. A Impossibile impostare le intestazioni dopo che sono state inviate verrà generato un messaggio di errore perché res.json()viene chiamato due volte, ovvero vengono inviate due risposte.

È possibile inviare una sola risposta per richiesta!


L'errore nell'esempio di codice sopra era evidente. Un problema più tipico è quando hai diversi rami:

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

Questa route con callback allegato trova un'azienda in un database. Quando eseguiamo una query per un'azienda che non esiste, entriamo nella else iffiliale e inviamo una risposta 404. Dopodiché, continueremo con la prossima dichiarazione che invia anche una risposta. Ora abbiamo inviato due risposte e verrà visualizzato il messaggio di errore. Possiamo correggere questo codice assicurandoci di inviare una sola risposta:

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

o restituendo quando viene inviata la risposta:

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

Un grande peccatore sono le funzioni asincrone. Prendi la funzione da questa domanda, ad esempio:

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

Qui abbiamo una funzione asincrona ( findOneAndUpdate()) nell'esempio di codice. Se non ci sono errori ( err) findOneAndUpdate()sarà chiamato. Poiché questa funzione è asincrona, res.json(doc1)verrà chiamata immediatamente. Supponiamo che non ci siano errori in findOneAndUpdate(). L' res.json(doc2)nel elseverrà poi chiamato. Sono state ora inviate due risposte e viene visualizzato il messaggio di errore Impossibile impostare le intestazioni .

La correzione, in questo caso, sarebbe rimuovere il res.json(doc1). Per inviare entrambi i documenti al client, res.json()nell'altro potrebbe essere scritto come res.json({ article: doc1, user: doc2 }).


2
Sei all'interno di una funzione asincrona, e deve return ilres.json
Genovo

Il mio problema stava usando res.sendin for loop.
Maihan Nijat,

1
Questo alla fine mi ha aiutato a capire e risolvere il problema, grazie mille :)
Pankaj Parkar,

grazie mille mi hai risparmiato tempo.
Mohammad Faisal,

Questa è sicuramente la risposta migliore!
Juanma Menendez,

53

Ho avuto lo stesso problema e mi sono reso conto che era perché stavo chiamando res.redirectsenza una returndichiarazione, quindi la nextfunzione veniva chiamata subito dopo:

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

Che avrebbe dovuto essere:

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

43

Molte persone hanno riscontrato questo errore. È un aspetto confuso con l'elaborazione asincrona. Molto probabilmente parte del codice sta impostando le intestazioni nel primo tick e quindi si esegue una richiamata asincrona in un tick futuro. Nel mezzo, l'intestazione della risposta viene inviata, ma poi ulteriori intestazioni (come un reindirizzamento 30X) tentano di aggiungere intestazioni extra, ma è troppo tardi poiché l'intestazione della risposta è già stata trasmessa.

Non sono sicuro di cosa stia causando il tuo errore, ma guardo ai callback come potenziali aree da investigare.

Un semplice consiglio per semplificare il tuo codice. Sbarazzati di app.configure()e basta chiamare app.usedirettamente nel tuo ambito di massimo livello.

Vedi anche il modulo everyauth , che utilizza Facebook e una dozzina di altri provider di autenticazione di terze parti.


Un reindirizzamento 30X è un codice di risposta HTTP. w3.org/Protocols/rfc2616/rfc2616-sec10.html I codici 300-399 sono diverse varianti di reindirizzamento, con 302 e 301 comunemente usati per inviare il client a un URL alternativo. Quando si esegue response.redirect (...) nel nodo, nella risposta verrà inviata un'intestazione di reindirizzamento 30X.
Peter Lyons,

3
Ohhhh. Stavo immaginando 30 reindirizzamenti di fila o qualcosa del genere
Janac Meena,

17

Ho bollito la testa su questo problema ed è successo a causa di un errore incurante nella gestione dei callback. i callback non restituiti fanno sì che la risposta venga impostata due volte.!

Il mio programma aveva un codice che convalida la richiesta e interroga il DB. dopo la convalida in caso di errore, stavo richiamando index.js con gli errori di convalida. E se la convalida passa, va avanti e colpisce il db con esito positivo / negativo.

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

Quello che stava succedendo è: la convalida in caso di errore fallisce quando viene richiamata la richiamata e viene impostata la risposta. Ma non restituito. Quindi continua ancora il metodo passa a db e colpisce successo / fallimento. Richiama di nuovo lo stesso callback e ora imposta la risposta due volte.

Quindi la soluzione è semplice, è necessario "restituire" il callback in modo che il metodo non continui l'esecuzione, una volta che si è verificato l'errore e quindi impostare l'oggetto risposta una volta

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

1
Grazie! Anche questo è stato il mio problema. Ho appena fatto un ctrl + f e ho trovato un callback(...)senza un return;dopo che alla fine stava facendo res.send(...)chiamare due volte.

15

Questo tipo di errore verrà visualizzato quando si passano le dichiarazioni dopo aver inviato una risposta.

Per esempio:

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

Si verificherà l'errore visualizzato, poiché una volta inviata la risposta, res.sendnon verrà eseguito quanto segue .

Se vuoi fare qualcosa, dovresti farlo prima di inviare la risposta.


Questo è stato il mio problema esatto :)
Joel Balmer,

6

A volte potresti ricevere questo errore quando provi a chiamare la funzione next () dopo res.end o res.send , prova a cancellare se hai next () dopo res.send o res.end nella tua funzione. Nota: qui next () significa che dopo aver risposto al client con la tua risposta ( es. Res.send o res.end ) stai ancora cercando di eseguire del codice per rispondere di nuovo, quindi non è legale.

Esempio :

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

rimuovere next()dalla funzione sopra e funzionerà.


6

Se si utilizzano le funzioni di callback, utilizzare returndopo il errblocco. Questo è uno degli scenari in cui questo errore può verificarsi.

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

Testato sulla versione Node v10.16.0ed express4.16.4


4

Questo errore si verifica quando si inviano 2 risposte. Per esempio :

if(condition A)
{ 

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

}

if (condition B){

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

Immagina se per qualche motivo le condizioni A e B sono vere, quindi nel secondo renderotterrai quell'errore


3

Nel mio caso è stata una risposta 304 (memorizzazione nella cache) a causare il problema.

La soluzione più semplice:

app.disable('etag');

Soluzione alternativa qui se si desidera un maggiore controllo:

http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/


Nel mio caso anche la risposta 304. Sto usando Fibre per l'elaborazione. In ogni caso la tua risposta aiuta molto. grazie
Dileep Stanley,

Qualcuno può spiegare quali sono le implicazioni per la rimozione dell'intestazione etag?
Mattwilsn,

2
Gli ETag consentono al server di non inviare contenuto che non è stato modificato. La disattivazione disabilita questa funzione. La voce ETag di Wikipedia ( en.wikipedia.org/wiki/HTTP_ETag ) ha una spiegazione più lunga.
blessed

3

Nel mio caso ciò è accaduto con React e Postal.js quando non ho annullato l'iscrizione a un canale nel componentWillUnmountcallback del mio componente React.


2

Per chiunque stia arrivando a questo e nessuna delle altre soluzioni ha aiutato, nel mio caso questo si è manifestato su un percorso che gestiva il caricamento delle immagini ma non gestiva i timeout , e quindi se il caricamento impiegava troppo tempo e scadeva, quando il callback veniva attivato dopo l'invio della risposta di timeout , la chiamata a res.send () ha provocato l'arresto anomalo poiché le intestazioni erano già impostate per tenere conto del timeout.

Questo è stato facilmente riprodotto impostando un timeout molto breve e colpendo il percorso con un'immagine abbastanza grande, l'incidente è stato riprodotto ogni volta.


1
come hai gestito il timeout per evitarlo?

2

Mi sono appena appoggiato a questo. È possibile passare le risposte tramite questa funzione:

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

2

Aggiungi questo middlware e funzionerà

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

2

Ciò accade quando la risposta è stata consegnata al client e di nuovo si sta tentando di fornire una risposta. Devi controllare nel tuo codice che da qualche parte stai restituendo di nuovo la risposta al client che causa questo errore. Controlla e restituisci la risposta una volta quando vuoi tornare.


1

Ho avuto questo problema mentre annidavo le promesse. Una promessa all'interno di una promessa restituirebbe 200 al server, ma poi la dichiarazione catch della promessa esterna restituirebbe una 500. Una volta risolto il problema, il problema è scomparso.


come hai risolto esattamente questo? Ho lo stesso problema con le promesse. Non posso evitare di annidarli ... quindi come posso interrompere l'esecuzione alla dichiarazione di ritorno?
Saurabh,

1

È venuto qui da Nuxt , il problema era nel asyncDatametodo del componente , ho dimenticato di returnpromettere che stava recuperando dati e impostando l'intestazione lì.


1

Verifica se il codice restituisce più istruzioni res.send () per una singola richiesta. Come quando ho avuto questo problema ...

Ho riscontrato questo problema nella mia applicazione di nodo Restify L'errore è stato quello

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

Stavo gestendo vari casi usando switch senza scrivere interruzioni. Per coloro che hanno poca familiarità con il caso switch sanno che senza interruzione, restituire le parole chiave. Il codice in questione e le righe successive verranno eseguite indipendentemente da cosa. Quindi, anche se voglio inviare un singolo res.send, a causa di questo errore è stato restituito più istruzioni res.send, che ha richiesto

l'errore non può impostare le intestazioni dopo che sono state inviate al client. Che è stato risolto aggiungendo questo o usando return prima di ogni metodo res.send () come return res.send (200)

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


grazie per la tua ispirazione mi è successo lo stesso. Ho risolto anche con altro se condizione.
Amr AbdelRahman,

1

È molto probabile che questo sia più una questione di nodo, il 99% delle volte è una doppia richiamata che ti fa rispondere due volte, o il prossimo () due volte ecc., Dannatamente sicuro. Risolto il mio problema stava usando next () all'interno di un loop. Rimuovi il successivo () dal loop o smetti di chiamarlo più di una volta.



1

Aggiungo semplicemente la parola chiave di ritorno come: return res.redirect("/great");e walla!


1

Ho avuto lo stesso problema causato dalla mangusta.

per risolvere il problema che è necessario abilitare Promises, in modo da poter aggiungere: mongoose.Promise = global.Promiseal codice, che consente l'utilizzo native js promises.

altre alternative a questa assunzione sono:

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

e

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

ma devi prima installare questi pacchetti.


1

l'errore trova da solo dopo un RND:

1) il mio codice di errore:

return res.sendStatus(200).json({ data: result });

2) il mio codice di successo

return res.status(200).json({ data: result });

la differenza è che ho usato sendStatus () invece di status () .


0

In Typescript, il mio problema era che non avevo chiuso la connessione al websocket dopo aver ricevuto un messaggio.

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

0

Se non si ottiene aiuto dall'alto: per noobs Il motivo di questo errore è l'invio di richieste più volte facci capire da alcuni casi: - 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();   
        }

`nella chiamata precedente next () due volte genererà un errore

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

qui rispondi viene inviato due volte controlla se hai già inviato una risposta


0

Nel mio caso succede a causa di più callback. Ho chiamato il next()metodo più volte durante il codice


0

Il mio problema era che avevo una setIntervalcorsa, che aveva un if/elseblocco, in cui il clearIntervalmetodo era all'interno di 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 {
            . . .

Mettere il clearIntervalprima che ha if/elsefatto il trucco.


0

Nel mio caso, In un ciclo, ho messo res.render()così potrebbe essere stato provato a chiamare più volte.


-1

Tutto ciò che dovevo fare in caso di questo errore era res.end ().

 auth.annonymousOnly = function(req, res, next) {
 // add other task here   
   res.end();    
  };

L'altro problema che potresti incontrare è il codice dopo res.json e res. Scrivi. In questo caso, è necessario utilizzare return per interrompere l'esecuzione dopo.

 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 
};
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.