Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

172
Visualizações
Express Error en el manejo de middleware para producción y desarrollo

Estoy tratando de hacer que el registro de errores de producción sea el predeterminado y mostrarle al usuario las cosas adicionales solo si la environment variable es development . Estoy tratando de hacer esto de la siguiente manera a continuación, pero recibo un mensaje que dice Cannot set headers after they are sent to the client .

 const ErrorClass = require('../routes/utils/ErrorClass'); const prodDBCastError = err => { const message = `Invalid ${err.path}: ${err.value}`; return new ErrorClass(message, 400); }; const prodDBDuplicateFieldsError = err => { const value = err.errmsg.match(/(["'])(\\?.)*?\1/)[0]; const message = `Duplicate field value: ${value}.`; return new ErrorClass(message, 400); }; const prodDBDValidationError = err => { const errors = Object.values(err.errors).map(el => el.message); const message = `Invalid input data. ${errors.join('. ')}`; return new ErrorClass(message, 400); }; const handleBadRequestDB = err => { const errors = err.message; const message = `Fixes: ${errors}`; return new ErrorClass(message, 400); }; const sendProdError = (err, res) => { if (err.isOperationalError){ res.status(err.status).json({ status: err.status, message: err.message, }); } else { res.status(500).json({ status: 'error', message: 'Server Issue.', }); } }; const sendVerboseDevError = (err, res) => { logger.error(err); err.status = err.status || 500; res.status(err.status).json({ status: err.status, name: err.name, path: err.path, errors: err.errors, message: err.message, stack: err.stack, }); }; module.exports = (err, req, res, next) => { if (process.env.APP_ENV === 'development'){ sendVerboseDevError(err, res); } if (err.name === 'CastError') {err = prodDBCastError(err);} if (err.name === 'MongoError') {err = prodDBDuplicateFieldsError(err);} if (err.name === 'ValidationError') {err = prodDBDValidationError(err);} if (err.name === 'Bad Request') {err = handleBadRequestDB(err);} sendProdError(err, res); };

Así es como se ve mi ErrorClass:

 class ErrorClass extends Error { constructor(message, status) { super(message); this.status = status; this.isOperationalError = true; Error.captureStackTrace(this, this.constructor); } } module.exports = ErrorClass;
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Te recomendaría cambiar tu código así.

Primero, evita llamar a res.json varias veces y también solo verifica si la aplicación se ejecuta en modo de desarrollo una vez. No hay necesidad de verificarlo con cada solicitud.

 var devHandler = (err, req, res, next) => { logger.error(err); err.status = err.status || 500; res.status(err.status).json({ status: err.status, name: err.name, path: err.path, errors: err.errors, message: err.message, stack: err.stack, }); }; var prodHandler = (err, req, res, next) => { if (err.name === 'CastError') {err = prodDBCastError(err);} if (err.name === 'MongoError') {err = prodDBDuplicateFieldsError(err);} if (err.name === 'ValidationError') {err = prodDBDValidationError(err);} if (err.name === 'Bad Request') {err = handleBadRequestDB(err);} if (err.isOperationalError){ res.status(err.status).json({ status: err.status, message: err.message, }); } else { res.status(500).json({ status: 'error', message: 'Server Issue.', }); } }; module.exports = process.env.APP_ENV === 'development' ? devHandler : prodHandler;
over 4 years ago · Santiago Trujillo Relatório

0

Esto se debe a que está intentando enviar datos desde sendProdError después de enviar datos desde sendVerboseDevError . res.json está enviando el json al cliente.

La razón detrás de esto se explica aquí https://stackoverflow.com/a/7086621/2232902

El objeto res en Express es una subclase de http.ServerResponse de Node.js (lea la fuente de http.js). Puede llamar a res.setHeader(nombre, valor) con la frecuencia que desee hasta que llame a res.writeHead(statusCode). Después de writeHead, los encabezados se integran y solo puede llamar a res.write(data) y finalmente a res.end(data)

Le recomendaría modificar sendProdError y sendVerboseDevError en constructProdError y constructVerboseDevError y luego enviar desde el mismo punto en el código.

referencia: https://stackoverflow.com/a/733858/2232902

over 4 years ago · Santiago Trujillo Relatório

0

Creo que el problema aquí es con las condiciones múltiples. Si la primera condición se cumple, se ejecutará la función "sendVerboseDevError". Que tiene el siguiente código

 res.status(err.status).json({ status: err.status, name: err.name, path: err.path, errors: err.errors, message: err.message, stack: err.stack, });

después de esta función, se establecerá el encabezado de respuesta. Luego, el flujo si va al resto de las condiciones si las condiciones son verdaderas y luego nuevamente se llama a otra función que está tratando de establecer la respuesta nuevamente. Es por eso que recibe el error "No se pueden configurar los encabezados después de enviarlos al cliente". Debe llamar al método "siguiente ()" después de configurar la respuesta. Por lo tanto, debe agregar el método "siguiente ()" en la parte inferior de cada condición.

algo como

 module.exports = (err, req, res, next) => { if (process.env.APP_ENV === 'development'){ sendVerboseDevError(err, res); next(); } if (err.name === 'CastError') { err = prodDBCastError(err); next(); } if (err.name === 'MongoError') { err = prodDBDuplicateFieldsError(err); next(); } if (err.name === 'ValidationError') { err = prodDBDValidationError(err); next(); } if (err.name === 'Bad Request') { err = handleBadRequestDB(err); next(); } sendProdError(err, res); next(); };

la siguiente función terminará la llamada API y devolverá la respuesta y evitará que establezca la respuesta nuevamente después de que cualquier función ejecutada antes de la actual haya establecido la respuesta.

PD: También puede llamar a la función "res.end()" en lugar de "next()".

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda