Mi aplicación node.js está modelada como la aplicación express / examples / mvc .
En una acción de controlador, quiero escupir un estado HTTP 400 con un mensaje http personalizado. De forma predeterminada, el mensaje de estado http es "Solicitud incorrecta":
HTTP/1.1 400 Bad Request
Pero quiero enviar
HTTP/1.1 400 Current password does not match
Intenté varias formas, pero ninguna de ellas configuró el mensaje de estado http en mi mensaje personalizado.
Mi función de controlador de solución actual se ve así:
exports.check = function( req, res) {
if( req.param( 'val')!=='testme') {
res.writeHead( 400, 'Current password does not match', {'content-type' : 'text/plain'});
res.end( 'Current value does not match');
return;
}
// ...
}
Todo funciona bien pero ... parece que no es la forma correcta de hacerlo.
¿Hay alguna forma mejor de configurar el mensaje de estado http usando express?
Respuestas:
Puede consultar esta documentación de
res.send(400, 'Current password does not match')
Look express 3.x para obtener más detallesACTUALIZAR para Expressjs 4.x
Úselo de esta manera (vea los documentos express 4.x ):
res.status(400).send('Current password does not match'); // or res.status(400); res.send('Current password does not match');
fuente
res.status(400).send('Current password does not match');
ejemplo me funciona para Express 4.Express ^4.16.2
Ninguna de las respuestas existentes logra lo que pidió originalmente el OP, que es anular la Frase de motivo predeterminada (el texto que aparece inmediatamente después del código de estado) enviado por Express.
Lo que quieres es
res.statusMessage
. Esto no es parte de Express, es una propiedad del objeto http.Response subyacente en Node.js 0.11+.Puede usarlo así (probado en Express 4.x):
function(req, res) { res.statusMessage = "Current password does not match"; res.status(400).end(); }
Luego use
curl
para verificar que funciona:$ curl -i -s http://localhost:3100/ HTTP/1.1 400 Current password does not match X-Powered-By: Express Date: Fri, 08 Apr 2016 19:04:35 GMT Connection: keep-alive Content-Length: 0
fuente
statusMessage
en algo diferente al mensaje estándar asignado al StatusCoderes.nativeResponse.statusMessage
En el lado del servidor (middleware Express):
if(err) return res.status(500).end('User already exists.');
Manejar en el lado del cliente
Angular:-
$http()..... .error(function(data, status) { console.error('Repos error', status, data);//"Repos error" 500 "User already exists." });
jQuery: -
$.ajax({ type: "post", url: url, success: function (data, text) { }, error: function (request, status, error) { alert(request.responseText); } });
fuente
Una forma elegante de manejar errores personalizados como este en Express es:
function errorHandler(err, req, res, next) { var code = err.code; var message = err.message; res.writeHead(code, message, {'content-type' : 'text/plain'}); res.end(message); }
(también puede usar express 'incorporado express.errorHandler para esto)
Luego, en su middleware, antes de sus rutas:
Luego, donde desea crear el error 'La contraseña actual no coincide':
function checkPassword(req, res, next) { // check password, fails: var err = new Error('Current password does not match'); err.code = 400; // forward control on to the next registered error handler: return next(err); }
fuente
Puedes usarlo así
return res.status(400).json({'error':'User already exists.'});
fuente
Mi caso de uso es enviar un mensaje de error JSON personalizado, ya que estoy usando Express para alimentar mi API REST. Creo que este es un escenario bastante común, por lo que me enfocaré en eso en mi respuesta.
Version corta:
Manejo rápido de errores
app.use(function(err, req, res, next) { if (err instanceof JSONError) { res.status(err.status).json({ status: err.status, message: err.message }); } else { next(err); } });
Genere errores desde cualquier punto del código haciendo:
var JSONError = require('./JSONError'); var err = new JSONError(404, 'Uh oh! Can't find something'); next(err);
Versión larga
La forma canónica de lanzar errores es:
var err = new Error("Uh oh! Can't find something"); err.status = 404; next(err)
De forma predeterminada, Express maneja esto empaquetándolo cuidadosamente como una Respuesta HTTP con el código 404, y el cuerpo consiste en la cadena del mensaje adjunta con un seguimiento de la pila.
Esto no funciona para mí cuando uso Express como servidor REST, por ejemplo. Querré que el error se devuelva como JSON, no como HTML. Definitivamente tampoco querré que mi seguimiento de pila se mueva a mi cliente.
Puedo enviar JSON como respuesta usando
req.json()
, por ejemplo. algo comoreq.json({ status: 404, message: 'Uh oh! Can't find something'})
. Opcionalmente, puedo configurar el código de estado usandoreq.status()
. Combinando los dos:req.status(404).json({ status: 404, message: 'Uh oh! Can't find something'});
Esto funciona a las mil maravillas. Dicho esto, me resulta bastante difícil de escribir cada vez que tengo un error, y el código ya no se auto-documenta como lo
next(err)
era el nuestro . Parece demasiado similar a cómo se envía una respuesta JSON normal (es decir, válida). Además, cualquier error arrojado por el enfoque canónico aún resulta en una salida HTML.Aquí es donde entra en juego el middleware de manejo de errores de Express. Como parte de mis rutas, defino:
app.use(function(err, req, res, next) { console.log('Someone tried to throw an error response'); });
También hago una subclase de Error en una clase JSONError personalizada:
JSONError = function (status, message) { Error.prototype.constructor.call(this, status + ': ' + message); this.status = status; this.message = message; }; JSONError.prototype = Object.create(Error); JSONError.prototype.constructor = JSONError;
Ahora, cuando quiero lanzar un error en el código, lo hago:
var err = new JSONError(404, 'Uh oh! Can't find something'); next(err);
Volviendo al middleware de manejo de errores personalizado, lo modifico a:
app.use(function(err, req, res, next) { if (err instanceof JSONError) { res.status(err.status).json({ status: err.status, message: err.message }); } else { next(err); } }
Subclasificar el error en JSONError es importante, ya que sospecho que Express
instanceof Error
comprueba el primer parámetro que se pasa anext()
para determinar si se debe invocar un controlador normal o un controlador de errores. Puedo eliminar elinstanceof JSONError
cheque y hacer modificaciones menores para asegurarme de que los errores inesperados (como un bloqueo) también devuelvan una respuesta JSON.fuente
Al usar Axios, puede recuperar el mensaje de respuesta personalizado con:
Axios.get(“your_url”) .then(data => { ... do something }.catch( err => { console.log(err.response.data) // you want this })
... después de configurarlo en Express como:
res.status(400).send(“your custom message”)
fuente
Si su objetivo es simplemente reducirlo a una sola línea, puede confiar un poco en los valores predeterminados ...
return res.end(res.writeHead(400, 'Current password does not match'));
fuente
Bueno, en el caso de Restify deberíamos usar el
sendRaw()
métodoLa sintaxis es:
res.sendRaw(200, 'Operation was Successful', <some Header Data> or null)
fuente