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?
javascript
node.js
express
DjangoRocks
fuente
fuente
Respuestas:
El
res
objeto en Express es una subclase de Node.jshttp.ServerResponse
( lea la fuente http.js ). Se le permite llamarres.setHeader(name, value)
con la frecuencia que desee hasta que llameres.writeHead(statusCode)
. DespuéswriteHead
, los encabezados se hornean y solo puedes llamarres.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.req
esnull
). y dado que el error ocurrió dentro de su actualfunction(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.jssetHeader
arrojó 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 :
res.writeContinue()
res.statusCode = 404
res.setHeader(name, value)
res.getHeader(name)
res.removeHeader(name)
res.header(key[, val])
(Solo expreso)res.charset = 'utf-8'
(Solo Express; solo afecta a métodos específicos de Express)res.contentType(type)
(Solo expreso)La respuesta debe estar en la cabeza y se convierte en cuerpo :
res.writeHead(statusCode, [reasonPhrase], [headers])
La respuesta puede estar en Cabeza / Cuerpo y permanece en Cuerpo :
res.write(chunk, encoding='utf8')
La respuesta puede estar en Cabeza / Cuerpo y se termina :
res.end([data], [encoding])
La respuesta puede estar en Cabeza / Cuerpo y permanece en su estado actual:
res.addTrailers(headers)
La respuesta debe estar en la cabeza y se termina :
return next([err])
(Solo Connect / Express)function(req, res, next)
(solo Connect / Express)res.send(body|status[, headers|status[, status]])
(Solo expreso)res.attachment(filename)
(Solo expreso)res.sendfile(path[, options[, callback]])
(Solo expreso)res.json(obj[, headers|status[, status]])
(Solo expreso)res.redirect(url[, status])
(Solo expreso)res.cookie(name, val[, options])
(Solo expreso)res.clearCookie(name[, options])
(Solo expreso)res.render(view[, options[, fn]])
(Solo expreso)res.partial(view[, options])
(Solo expreso)fuente
return
antesnext()
, ¡gracias esto me señaló el error!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.use
método, agrega elementos paraServer.prototype.stack
conectarse (al menos con el actualnpm 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()
medidaServer.prototype.handle
que se completa el método principal , notará ese:response.headerSent
es verdad.Entonces, arroja un error. Pero el error que arroja es solo esta respuesta básica (del
http.js
código fuente de conexión :Ahí mismo, está llamando
res.setHeader('Content-Type', 'text/plain');
, lo que es probable que haya configurado en surender
método, sin llamar a response.end () , algo como:La forma en que todo debe estructurarse es así:
Buen middleware
Middleware problemático
El middleware problemático establece el encabezado de respuesta sin llamadas
response.end()
y llamadasnext()
, lo que confunde el servidor de connect.fuente
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:
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:
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:
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 if
sucursal 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:o regresando cuando se envía la respuesta:
Un gran pecador son las funciones asincrónicas. Tome la función de esta pregunta, por ejemplo:
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íncronares.json(doc1)
, se llamará inmediatamente. Suponga que no hay errores enfindOneAndUpdate()
. Elres.json(doc2)
en elelse
será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, elres.json()
en el otro podría escribirse comores.json({ article: doc1, user: doc2 })
.fuente
return
alres.json
res.send
bucle for.Tuve este mismo problema y me di cuenta de que era porque estaba llamando
res.redirect
sin unareturn
declaración, por lo que lanext
función también se llamaba inmediatamente después:Que debería haber sido:
fuente
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 llameapp.use
directamente 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.
fuente
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.
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
fuente
callback(...)
sin unreturn;
después que finalmente causóres.send(...)
que se llamara dos veces.Este tipo de error se obtendrá cuando pase declaraciones después de enviar una respuesta.
Por ejemplo:
Se producirá el error que está viendo, porque una vez que se ha enviado la respuesta,
res.send
no se ejecutará lo siguiente.Si desea hacer algo, debe hacerlo antes de enviar la respuesta.
fuente
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:
fuente
Si está utilizando funciones de devolución de llamada, use
return
después delerr
bloque. Este es uno de los escenarios en los que puede ocurrir este error.Probado en la versión Node
v10.16.0
y express4.16.4
fuente
Este error ocurre cuando envía 2 respuestas. Por ejemplo :
Imagínese si por alguna razón las condiciones A y B son ciertas, por lo que en el segundo
render
obtendrá ese errorfuente
En mi caso, fue una respuesta 304 (almacenamiento en caché) lo que causó el problema.
La solución más fácil:
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/
fuente
En mi caso, esto sucedió con React y postal.js cuando no me di de baja de un canal en la
componentWillUnmount
devolución de llamada de mi componente React.fuente
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.
fuente
Solo se inclinó esto. Puede pasar las respuestas a través de esta función:
fuente
Agregue este middlware y funcionará
fuente
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.
fuente
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ó.
fuente
Llegué aquí desde nuxt , el problema estaba en el
asyncData
método del componente , olvidéreturn
prometer que estaba obteniendo datos y configurando el encabezado allí.fuente
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ó
switch (status) { case -1: res.send(400); break; case 0: res.send(200); break; default: res.send(500); break; }
fuente
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.
fuente
Recibí un error similar cuando intenté enviar una respuesta dentro de una función de bucle. La solución simple era mover el
fuera del ciclo ya que solo puede enviar el encabezado de respuesta una vez.
https://www.tutorialspoint.com/nodejs/nodejs_response_object.htm
fuente
Simplemente agrego la palabra clave de retorno como: ¡
return res.redirect("/great");
y walla!fuente
Tuve el mismo problema causado por la mangosta.
para corregir que debe habilitar
Promises
, para que pueda agregar:mongoose.Promise = global.Promise
a su código, que permite usarnative js promises
.Otras alternativas a esta solución son:
y
pero primero necesita instalar estos paquetes.
fuente
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 () .
fuente
En Typecript, mi problema fue que no cerré la conexión websocket después de recibir un mensaje.
fuente
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. `
`en la llamada anterior next () dos veces generará un error
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
fuente
En mi caso ocurre debido a múltiples devoluciones de llamada. He llamado al
next()
método varias veces durante el códigofuente
Mi problema fue que tenía una
setInterval
ejecución, que tenía unif/else
bloque, donde elclearInterval
método estaba dentro deelse
:Poner el
clearInterval
antes delif/else
hizo el truco.fuente
En mi caso, en un bucle, puse
res.render()
que podría haber intentado llamar varias veces.fuente
Todo lo que tenía que hacer en caso de este error era 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.
fuente