Error: no se pueden establecer encabezados después de enviarlos al cliente

726

Soy bastante nuevo en Node.js y tengo algunos problemas.

Estoy usando Node.js 4.10 y Express 2.4.3.

Cuando intento acceder a http://127.0.0.1:8888/auth/facebook , se me redirigirá a http://127.0.0.1:8888/auth/facebook_callback .

Luego recibí el siguiente error:

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)

El siguiente es mi 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);

¿Puedo saber qué está mal con mi código?

DjangoRocks
fuente
respuesta simple de visionmedia: github.com/visionmedia/express/issues/634
shi11i
2
Google me envió a esta pregunta, pero las versiones más nuevas de ExpressJS tienen res.headersSent boolean que se puede usar para verificar si es seguro configurar / enviar encabezados
Julian Soro

Respuestas:

1113

El resobjeto en Express es una subclase de Node.jshttp.ServerResponse ( lea la fuente http.js ). Se le permite llamar res.setHeader(name, value)con la frecuencia que desee hasta que llame res.writeHead(statusCode). Después writeHead, los encabezados se hornean y solo puedes llamar res.write(data), y finalmenteres.end(data) .

El error "Error: no se pueden establecer encabezados después de que se envían". significa que ya está en el estado Cuerpo o Terminado, pero alguna función intentó establecer un encabezado o código de estado. Cuando vea este error, intente buscar cualquier cosa que intente enviar un encabezado después de que parte del cuerpo ya se haya escrito. Por ejemplo, busque devoluciones de llamada que se llaman accidentalmente dos veces, o cualquier error que ocurra después de enviar el cuerpo.

En su caso, llamó res.redirect(), lo que provocó que la respuesta se terminara. Entonces su código arrojó un error ( res.reqes null). y dado que el error ocurrió dentro de su actual function(req, res, next)(no dentro de una devolución de llamada), Connect pudo detectarlo y luego intentó enviar una página de 500 errores. Pero como los encabezados ya se enviaron, Node.js setHeaderarrojó el error que viste.

Lista completa de los métodos de respuesta Node.js / Express y cuándo deben llamarse:

La respuesta debe estar en Head y permanece en 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]) (Solo expreso)
  7. res.charset = 'utf-8' (Solo Express; solo afecta a métodos específicos de Express)
  8. res.contentType(type) (Solo expreso)

La respuesta debe estar en la cabeza y se convierte en cuerpo :

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

La respuesta puede estar en Cabeza / Cuerpo y permanece en Cuerpo :

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

La respuesta puede estar en Cabeza / Cuerpo y se termina :

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

La respuesta puede estar en Cabeza / Cuerpo y permanece en su estado actual:

  1. res.addTrailers(headers)

La respuesta debe estar en la cabeza y se termina :

  1. return next([err]) (Solo Connect / Express)
  2. Cualquier excepción dentro del middleware function(req, res, next)(solo Connect / Express)
  3. res.send(body|status[, headers|status[, status]]) (Solo expreso)
  4. res.attachment(filename) (Solo expreso)
  5. res.sendfile(path[, options[, callback]]) (Solo expreso)
  6. res.json(obj[, headers|status[, status]]) (Solo expreso)
  7. res.redirect(url[, status]) (Solo expreso)
  8. res.cookie(name, val[, options]) (Solo expreso)
  9. res.clearCookie(name[, options]) (Solo expreso)
  10. res.render(view[, options[, fn]]) (Solo expreso)
  11. res.partial(view[, options]) (Solo expreso)
yonran
fuente
13
Sí, verifique para llamar a next () u otro cb dos veces.
Tony Gutiérrez,
3
Los enlaces expresos parecen muertos
Korhan Ozturk
25
También tenga cuidado con este error clásico: res.redirect () no detiene la ejecución de la declaración ... así que regrese después de eso. De lo contrario, se podría ejecutar otro código que podría causar involuntariamente el famoso error de encabezado. Gracias por la explicación!
KLoozen el
Por lo general, es una buena idea usar return al final de su devolución de llamada para evitar esto
thethakuri
44
Cometí un error muy pequeño en mi middleware, no lo hice returnantes next(), ¡gracias esto me señaló el error!
illcrx
113

Me encontré con este error también por un tiempo. Creo (espero) haberlo comprendido, quería escribirlo aquí como referencia.

Cuando agrega middleware para conectar o expresar (que se basa en conectar) usando el app.usemétodo, agrega elementos para Server.prototype.stackconectarse (al menos con el actual npm install connect, que se ve bastante diferente del único github a partir de esta publicación). Cuando el servidor recibe una solicitud, itera sobre la pila, llamando al (request, response, next)método.

El problema es que si en uno de los elementos de middleware escribe en el cuerpo de respuesta o en los encabezados (parece que es o por alguna razón), pero no llama response.end()y usted llama anext() medida Server.prototype.handleque se completa el método principal , notará ese:

  1. no hay más elementos en la pila, y / o
  2. Eso response.headerSentes verdad.

Entonces, arroja un error. Pero el error que arroja es solo esta respuesta básica (del http.jscódigo fuente de conexión :

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

Ahí mismo, está llamando res.setHeader('Content-Type', 'text/plain');, lo que es probable que haya configurado en su rendermétodo, sin llamar a response.end () , algo como:

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

La forma en que todo debe estructurarse es así:

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

El middleware problemático establece el encabezado de respuesta sin llamadas response.end()y llamadas next(), lo que confunde el servidor de connect.

Lance Pollard
fuente
77
+1 Esta es una gran explicación, pero ¿qué pasa con el caso cuando usa res.redirect ()? Con frecuencia me encuentro con este problema cuando el middleware intenta redirigir en función de alguna condición. ¿El middleware no debe redirigir, según su ejemplo de "Good Middleware"?
qodeninja
Sabes que tengo este problema exacto debido a lo que llamas un middleware problemático, sin embargo, necesito un caso en el que devuelva la respuesta pero me gustaría realizar un procesamiento adicional en un controlador separado como parte de la cadena, ¿cómo hago para suprimir este error? ?
iQ.
57

Algunas de las respuestas en estas preguntas y respuestas son incorrectas. La respuesta aceptada tampoco es muy "práctica", por lo que quiero publicar una respuesta que explique las cosas en términos más simples. Mi respuesta cubrirá el 99% de los errores que veo publicados una y otra vez. Por las razones reales detrás del error, eche un vistazo a la respuesta aceptada.


HTTP utiliza un ciclo que requiere una respuesta por solicitud. Cuando el cliente envía una solicitud (por ejemplo, POST o GET), el servidor solo debe enviarle una respuesta.

Este mensaje de error:

Error: no se pueden establecer encabezados después de enviarlos.

generalmente ocurre cuando envía varias respuestas para una solicitud. Asegúrese de que las siguientes funciones se invoquen solo una vez por solicitud:

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

(y algunos más que rara vez se usan, verifique la respuesta aceptada)

La devolución de llamada de ruta no volverá cuando se invoquen estas funciones res. Continuará ejecutándose hasta que llegue al final de la función o una declaración de retorno. Si desea volver al enviar una respuesta, puede hacerlo de esta manera: return res.send().


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

Cuando se envía una solicitud POST a / api / route1 , se ejecutará cada línea en la devolución de llamada. A No se pueden establecer encabezados después de que se envíen un mensaje de error porque res.json()se llama dos veces, lo que significa que se envían dos respuestas.

¡Solo se puede enviar una respuesta por solicitud!


El error en el ejemplo de código anterior fue obvio. Un problema más típico es cuando tienes varias ramas:

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

Esta ruta con devolución de llamada adjunta encuentra una empresa en una base de datos. Al hacer una consulta para una empresa que no existe, ingresaremos a la else ifsucursal y enviaremos una respuesta 404. Después de eso, continuaremos con la siguiente declaración que también envía una respuesta. Ahora hemos enviado dos respuestas y aparecerá el mensaje de error. Podemos corregir este código asegurándonos de enviar solo una respuesta:

.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 regresando cuando se envía la respuesta:

.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 gran pecador son las funciones asincrónicas. Tome la función de esta pregunta, por ejemplo:

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

Aquí tenemos una función asincrónica ( findOneAndUpdate()) en el ejemplo de código. Si no hay errores ( err) findOneAndUpdate()se llamará. Como esta función es asíncrona res.json(doc1), se llamará inmediatamente. Suponga que no hay errores en findOneAndUpdate(). El res.json(doc2)en el elseserán entonces invitados. Ahora se han enviado dos respuestas y aparece el mensaje de error No se pueden establecer encabezados .

La solución, en este caso, sería eliminar el res.json(doc1). Para enviar ambos documentos de vuelta al cliente, el res.json()en el otro podría escribirse como res.json({ article: doc1, user: doc2 }).

Mika Sundland
fuente
2
Estás dentro de una función asíncrona, y debe return alres.json
Genovo
Mi problema estaba usando el res.sendbucle for.
Maihan Nijat
1
Esto me ayudó al final a comprender y solucionar el problema, muchas gracias :)
Pankaj Parkar
muchas gracias me ahorras tiempo
Mohammad Faisal
¡Esta es definitivamente la mejor respuesta!
Juanma Menéndez
53

Tuve este mismo problema y me di cuenta de que era porque estaba llamando res.redirectsin una returndeclaración, por lo que la nextfunción también se llamaba inmediatamente después:

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

Que debería haber sido:

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

Mucha gente golpeó este error. Es confuso esto con el procesamiento asíncrono. Lo más probable es que parte de su código establezca encabezados en el primer tic y luego esté ejecutando una devolución de llamada asíncrona en un tick futuro. En el medio, el encabezado de respuesta se envía, pero luego otros encabezados (como una redirección 30X) intentan agregar encabezados adicionales, pero es demasiado tarde ya que el encabezado de respuesta ya se ha transmitido.

No estoy seguro de qué es exactamente lo que está causando su error, pero considere cualquier devolución de llamada como áreas potenciales para investigar.

Un consejo fácil para simplificar su código. Deshágase app.configure()y simplemente llame app.usedirectamente en su alcance de nivel superior.

Vea también el módulo everyauth , que hace Facebook y una docena de otros proveedores de autenticación de terceros.

Peter Lyons
fuente
Una redirección 30X es un código de respuesta HTTP. w3.org/Protocols/rfc2616/rfc2616-sec10.html Los códigos 300-399 son diferentes variaciones de redireccionamiento, con 302 y 301 que se usan comúnmente para enviar al cliente a una URL alternativa. Cuando responda response.redirect (...) en el nodo, se enviará un encabezado de redireccionamiento 30X en la respuesta.
Peter Lyons
3
Ohhhh Estaba imaginando 30 redirecciones seguidas o algo así
Janac Meena
17

Herví la cabeza sobre este problema y sucedió debido a un error descuidado en el manejo de las devoluciones de llamada. las devoluciones de llamada no devueltas hacen que la respuesta se establezca dos veces.

Mi programa tenía un código que validaba la solicitud y consultaba la base de datos. después de validar si hay un error, estaba volviendo a llamar a index.js con los errores de validación. Y si la validación pasa, sigue adelante y golpea la base de datos con éxito / fracaso.

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

Lo que sucedía es: la validación en caso de error falla, se llama la devolución de llamada y se establece la respuesta. Pero no regresó. Por lo tanto, aún continúa, el método va a db y alcanza el éxito / fracaso. Llama a la misma devolución de llamada nuevamente, lo que hace que la respuesta se configure dos veces ahora.

Entonces, la solución es simple, debe 'devolver' la devolución de llamada para que el método no continúe ejecutándose, una vez que se haya producido el error y, por lo tanto, configure el objeto de respuesta una vez

  var error = validateRequestDetails("create",queryReq);
    if (error)
        callback(error, null);
        return;
    else
       some code 
       callback(null, success);
aleatoriedad
fuente
1
¡Gracias! Esto resultó ser mi problema también. Acabo de hacer un ctrl + f y encontré un callback(...)sin un return;después que finalmente causó res.send(...)que se llamara dos veces.
15

Este tipo de error se obtendrá cuando pase declaraciones después de enviar una respuesta.

Por ejemplo:

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

Se producirá el error que está viendo, porque una vez que se ha enviado la respuesta, res.sendno se ejecutará lo siguiente.

Si desea hacer algo, debe hacerlo antes de enviar la respuesta.

Troyano
fuente
Este fue mi problema exacto :)
Joel Balmer
6

A veces puede aparecer este error cuando intenta llamar a la función next () después de res.end o res.send , intente eliminar si tiene next () después de res.send o res.end en su función. Nota: aquí next () significa que después de responder al cliente con su respuesta ( es decir, res.send o res.end ) todavía está intentando ejecutar algún código para responder de nuevo, por lo que no es legal.

Ejemplo:

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

eliminar next()de la función anterior y funcionará.

Surendra Parchuru
fuente
6

Si está utilizando funciones de devolución de llamada, use returndespués del errbloque. Este es uno de los escenarios en los que puede ocurrir este error.

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

Probado en la versión Node v10.16.0y express4.16.4

Krishnadas PC
fuente
4

Este error ocurre cuando envía 2 respuestas. Por ejemplo :

if(condition A)
{ 

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

}

if (condition B){

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

Imagínese si por alguna razón las condiciones A y B son ciertas, por lo que en el segundo renderobtendrá ese error

Badr Bellaj
fuente
3

En mi caso, fue una respuesta 304 (almacenamiento en caché) lo que causó el problema.

La solución más fácil:

app.disable('etag');

Solución alternativa aquí si desea más control:

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

sangrado
fuente
En mi caso también la respuesta 304. Estoy usando fibras para el procesamiento. De cualquier manera, su respuesta ayuda mucho. gracias
Dileep stanley
¿Alguien puede explicar cuáles son las implicaciones para eliminar el encabezado etag?
mattwilsn
2
Los ETags permiten que el servidor no envíe contenido que no ha cambiado. Desactivarlo desactiva esta función. La entrada de ETag wikipedia ( en.wikipedia.org/wiki/HTTP_ETag ) tiene una explicación más larga.
sangrado
3

En mi caso, esto sucedió con React y postal.js cuando no me di de baja de un canal en la componentWillUnmountdevolución de llamada de mi componente React.

Zoltán
fuente
2

Para cualquiera que esté llegando a esto y ninguna de las otras soluciones ayudó, en mi caso esto se manifestó en una ruta que manejó la carga de imágenes pero no manejó los tiempos de espera , y por lo tanto, si la carga tomó demasiado tiempo y se agotó el tiempo, cuando se activó la devolución de llamada después de que se envió la respuesta de tiempo de espera , llamar a res.send () resultó en el bloqueo ya que los encabezados ya estaban configurados para dar cuenta del tiempo de espera.

Esto se reprodujo fácilmente estableciendo un tiempo de espera muy corto y golpeando la ruta con una imagen decentemente grande, el bloqueo se reproducía cada vez.

Miguel
fuente
1
¿Cómo manejaste el tiempo de espera para evitar esto?
2

Solo se inclinó esto. Puede pasar las respuestas a través de esta función:

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
fuente
2

Agregue este middlware y 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();
});
RANJAN CENIZO
fuente
2

Esto sucede cuando se entregó la respuesta al cliente y nuevamente está intentando dar una respuesta. Debe verificar en su código que en algún lugar está devolviendo la respuesta al cliente nuevamente, lo que causa este error. Verifique y devuelva la respuesta una vez cuando desee regresar.

Ankit Manchanda
fuente
1

Tuve este problema cuando estaba anidando promesas. Una promesa dentro de una promesa devolvería 200 al servidor, pero luego la declaración catch de la promesa externa devolvería un 500. Una vez que solucioné esto, el problema desapareció.

apresurarse
fuente
¿Cómo exactamente arreglaste esto? Tengo el mismo problema con las promesas. No puedo evitar anidarlos ... entonces, ¿cómo detengo la ejecución en la declaración de devolución?
Saurabh
1

Llegué aquí desde nuxt , el problema estaba en el asyncDatamétodo del componente , olvidé returnprometer que estaba obteniendo datos y configurando el encabezado allí.

Nick Synev
fuente
1

Verifique si su código está devolviendo múltiples res.send () declaraciones para una sola solicitud. Como cuando tuve este problema ...

Era este problema en mi aplicación de nodo restify. El error fue que

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

Estaba manejando varios casos usando switch sin escribir break. Para aquellos poco familiarizados con el caso de cambio, sepa que sin interrupción, devuelva palabras clave. El código en mayúsculas y las siguientes líneas se ejecutarán sin importar qué. Entonces, aunque quiero enviar un solo res.send, debido a este error, estaba devolviendo múltiples declaraciones res.send, lo que provocó

error no puede establecer encabezados después de que se envían al cliente. Que se resolvió agregando esto o 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
fuente
gracias por tu inspiración me pasó lo mismo. Lo resolví también con else if condition.
Amr AbdelRahman
1

Es muy probable que esto sea más una cuestión de nodo, el 99% de las veces es una devolución de llamada doble que hace que responda dos veces, o la próxima () dos veces, etc., maldita sea. Resolvió que mi problema era usar next () dentro de un bucle. Elimine el next () del bucle o deje de llamarlo más de una vez.

Ahmad Naved
fuente
1

Simplemente agrego la palabra clave de retorno como: ¡ return res.redirect("/great");y walla!

Emmanuel Benson
fuente
1

Tuve el mismo problema causado por la mangosta.

para corregir que debe habilitar Promises, para que pueda agregar: mongoose.Promise = global.Promisea su código, que permite usarnative js promises .

Otras alternativas a esta solución son:

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

y

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

pero primero necesita instalar estos paquetes.

sina
fuente
1

error encontrar por sí mismo después de un RND:

1) mi código de error:

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

2) mi código de éxito

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

La diferencia es que utilicé sendStatus () en lugar de status () .

Nagender Pratap Chauhan
fuente
0

En Typecript, mi problema fue que no cerré la conexión websocket después de recibir un mensaje.

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

Si no obtiene ayuda de lo anterior: para los novatos La razón detrás de este error es el envío de la solicitud varias veces, déjenos entender de algunos 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();   
        }

`en la llamada anterior next () dos veces generará un error

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

aquí responder es enviar dos veces verifique si ya envió una respuesta

Sanjay
fuente
0

En mi caso ocurre debido a múltiples devoluciones de llamada. He llamado al next()método varias veces durante el código

Señor ratnadeep
fuente
0

Mi problema fue que tenía una setIntervalejecución, que tenía un if/elsebloque, donde el clearIntervalmétodo estaba dentro de 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 {
            . . .

Poner el clearIntervalantes del if/elsehizo el truco.

Mike K
fuente
0

En mi caso, en un bucle, puse res.render()que podría haber intentado llamar varias veces.

Hasan Sefa Ozalp
fuente
-1

Todo lo que tenía que hacer en caso de este error era res.end ().

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

El otro problema que podría enfrentar es que hay código después de res.json y res. escribir. En este caso, debe usar return para detener la ejecución después de eso.

 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 
};
descifrador
fuente