validacion - validar formulario javascript html5
Error: no se pueden establecer encabezados después de que se envían al cliente (20)
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 , seré redirigido a http://127.0.0.1:8888/auth/facebook_callback .
Entonces 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?
A veces puede obtener este error cuando intenta llamar a la función next () después de reenviar o reenviar , intente eliminar si tiene next () después de reenviar o res.end en su función. Nota: aquí siguiente () significa que después de responder al cliente con su respuesta ( es decir, reenviar o reenviar ) 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
});
Elimina
next()
de la función anterior y funcionará.
Agrega 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();
});
El objeto res
en Express es una subclase de http.ServerResponse
de Node.js ( lea la fuente http.js ). Se le permite llamar a res.setHeader(name, value)
con la frecuencia que desee hasta que llame a res.writeHead(statusCode)
. Después de writeHead
, los encabezados son horneados y solo puede llamar a res.write(data)
, y finalmente a res.end(data)
.
El error "Error: no se pueden establecer los encabezados después de que se envían". significa que ya está en el estado Cuerpo o Finalizado, pero alguna función intentó establecer un encabezado o un 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 haya sido escrito. Por ejemplo, busque devoluciones de llamada que se llamen accidentalmente dos veces, o cualquier error que ocurra después de que se envíe el cuerpo.
En su caso, llamó a res.redirect()
, lo que provocó que la respuesta se finalizara. Luego su código arrojó un error ( res.req
es null
). y como el error ocurrió dentro de su function(req, res, next)
real 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 ya se enviaron los encabezados, setHeader
de Node.js 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 Jefe y permanece en Jefe :
-
res.writeContinue()
-
res.statusCode = 404
-
res.setHeader(name, value)
-
res.getHeader(name)
-
res.removeHeader(name)
-
res.header(key[, val])
(solo Express) -
res.charset = ''utf-8''
(solo Express; solo afecta los métodos específicos de Express) -
res.contentType(type)
(solo Express)
La respuesta debe estar en Cabeza y se convierte en Cuerpo :
La respuesta puede estar en cualquier Cabeza / Cuerpo y permanece en el Cuerpo :
La respuesta puede estar en cualquier Cabeza / Cuerpo y se termina :
La respuesta puede estar en cualquier Cabeza / Cuerpo y permanece en su estado actual:
La respuesta debe estar en Head y se termina :
-
return next([err])
(Connect / Express solamente) - Cualquier excepción dentro de la
function(req, res, next)
middlewarefunction(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 Express) -
res.json(obj[, headers|status[, status]])
(solo Express) -
res.redirect(url[, status])
(solo Express) -
res.cookie(name, val[, options])
(solo expreso) -
res.clearCookie(name[, options])
(solo Express) -
res.render(view[, options[, fn]])
(solo Express) -
res.partial(view[, options])
(solo expreso)
En Typescript, mi problema fue que no cerré la conexión de websocket después de recibir un mensaje.
WebSocket.on("message", (data) => {
receivedMessage = true;
doSomething(data);
localSocket.close(); //This close the connection, allowing
});
En mi caso sucede debido a múltiples devoluciones de llamada. He llamado el método next()
varias veces durante el código
En mi caso, esto sucedió con React y postal.js cuando no cancelé la suscripción de un canal en la devolución de llamada componentWillUnmount
de mi componente React.
En mi caso, fue una respuesta 304 (almacenamiento en caché) la que causó el problema.
La solución más fácil:
app.disable(''etag'');
Solución alternativa aquí si quieres más control:
Este tipo de error que 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");
Resultará en el error que está viendo, porque una vez que se haya enviado la res.send
, no se ejecutará el siguiente res.send
.
Si quieres hacer algo, debes hacerlo antes de enviar la respuesta.
Esto sucede cuando la respuesta fue entregada al cliente y nuevamente está intentando dar respuesta. Debe verificar en su código que en algún lugar está devolviendo la respuesta al cliente, lo que provoca este error. Marque y devuelva la respuesta una vez cuando quiera regresar
Herví mi cabeza sobre este problema y sucedió debido a un error por descuido en el manejo de las devoluciones de llamada. las devoluciones de llamadas no devueltas hacen que la respuesta se establezca dos veces.
Mi programa tenía un código que valida la solicitud y consulta la base de datos. después de validar si hay un error, estaba devolviendo la llamada a index.js con los errores de validación. Y si la validación pasa, sigue adelante y golpea la db con éxito / fracaso.
var error = validateRequestDetails("create",queryReq);
if (error)
callback(error, null);
else
some code
callback(null, success);
Lo que estaba ocurriendo es: la validación de la base falla, se invoca la devolución de llamada y se establece la respuesta. Pero no regresó. Así que aún continúa el método va a db y golpea el éxito / fracaso. Vuelve a llamar a la misma devolución de llamada, lo que hace que la respuesta se configure dos veces ahora.
Así que 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, configurar el objeto de respuesta una vez.
var error = validateRequestDetails("create",queryReq);
if (error)
callback(error, null);
return;
else
some code
callback(null, success);
Llegó aquí desde Nuxt , el problema estaba en el método asyncData
del componente, olvidé return
promesa que estaba buscando datos y configurando el encabezado allí.
Me encontré con este error también por un tiempo. Pienso (espero) que he envuelto mi cabeza alrededor de esto, quería escribirlo aquí como referencia.
Cuando agrega middleware para connect o express (que se basa en la conexión) utilizando el método app.use
, está agregando elementos a Server.prototype.stack
en la conexión (al menos con la actual npm install connect
, que se ve muy diferente a el github a partir de este post). Cuando el servidor recibe una solicitud, itera sobre la pila, llamando al método (request, response, next)
.
El problema es que si en uno de los elementos de middleware se escribe en el cuerpo de la respuesta o en los encabezados (parece que es cualquiera o por alguna razón), pero no llama a response.end()
y llama a next()
entonces como Server.prototype.handle
método Core Server.prototype.handle
se completa, notará que:
- no hay más elementos en la pila, y / o
- que
response.headerSent
es verdadero.
Por lo tanto, arroja un error. Pero el error que arroja es solo esta respuesta básica (del código fuente de http.js
conexión:
res.statusCode = 404;
res.setHeader(''Content-Type'', ''text/plain'');
res.end(''Cannot '' + req.method + '' '' + req.url);
Justo allí, está llamando res.setHeader(''Content-Type'', ''text/plain'');
, que es probable que haya establecido en su método de render
, sin llamar a response.end () , algo como:
response.setHeader("Content-Type", "text/html");
response.write("<p>Hello World</p>");
La forma en que todo necesita ser estructurado 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 llamar a response.end()
y llama a next()
, lo que confunde al servidor de conexión.
Mucha gente golpea este error. Es confuso esto con el procesamiento asíncrono. Lo más probable es que parte de su código esté configurando encabezados en la primera marca y luego esté ejecutando una devolución de llamada asíncrona en una marca futura. Mientras tanto, se envía el encabezado de respuesta, pero luego otros encabezados (como una redirección 30X) intentan agregar encabezados adicionales, pero es demasiado tarde porque 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 de app.configure () y simplemente llame a app.use directamente en su alcance de nivel superior.
Vea también el módulo everyauth , que hace Facebook y una docena de proveedores de autenticación de terceros.
Para cualquiera que haya llegado a esto y ninguna de las otras soluciones ayudó, en mi caso esto se manifestó en una ruta que manejaba la carga de imágenes pero que no controlaba los tiempos de espera , y por lo tanto, si la carga demoraba demasiado y se agotaba el tiempo de espera, cuando se disparó la devolución de llamada después de que se envió el tiempo de espera , al llamar a res.send () se produjo 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.
Sólo se inclinó esto. Puedes 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();
});
Si no recibió ayuda de lo de arriba: para noobs El motivo de este error es enviar la solicitud varias veces, entendámoslo en 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 siguiente () 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 comprobar si ya ha enviado una respuesta
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();
};
Tuve este mismo problema y me di cuenta de que era porque estaba llamando res.redirect sin una declaración de retorno, por lo que la siguiente función también fue llamada 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();
};
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 500. Una vez que solucioné esto, el problema desapareció.
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 enviar una respuesta a este.
Este mensaje de error:
Error: No se pueden establecer encabezados después de que se envían.
Por lo general, sucede cuando envía varias respuestas para una solicitud. Asegúrese de que las siguientes funciones sean llamadas 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 llamen 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 así: return res.send()
.
Tomemos 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. Se emitirá un mensaje de error No se pueden establecer los encabezados después de enviarlos porque se llama a res.json()
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 era 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 compañía que no existe, entraremos dentro de else if
ramifica 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 arreglar este código asegurándonos de que solo enviamos 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 volviendo 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 asíncronas. Tome la función de this 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 asíncrona ( findOneAndUpdate()
) en el ejemplo de código. Si no hay errores ( err
) se findOneAndUpdate()
. Debido a que esta función es asíncrona, se res.json(doc1)
inmediatamente. Supongamos que no hay errores en findOneAndUpdate()
. res.json(doc2)
en el else
. 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 al cliente, res.json()
en el else podría escribirse como res.json({ article: doc1, user: doc2 })
.