Meu aplicativo node.js é modelado como o aplicativo express / examples / mvc .
Em uma ação do controlador, quero exibir um status HTTP 400 com uma mensagem http personalizada. Por padrão, a mensagem de status http é "Bad Request":
HTTP/1.1 400 Bad Request
Mas eu quero enviar
HTTP/1.1 400 Current password does not match
Tentei várias maneiras, mas nenhuma delas definiu a mensagem de status http para minha mensagem personalizada.
Minha função de controlador de solução atual é assim:
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;
}
// ...
}
Tudo funciona bem, mas ... parece não ser a maneira certa de fazer isso.
Existe alguma maneira melhor de definir a mensagem de status http usando o expresso?
Respostas:
Você pode verificar esta documentação do
res.send(400, 'Current password does not match')
Look express 3.x para obter detalhesATUALIZAÇÃO para Expressjs 4.x
Use desta forma (veja os documentos express 4.x ):
res.status(400).send('Current password does not match'); // or res.status(400); res.send('Current password does not match');
fonte
res.status(400).send('Current password does not match');
exemplo funciona para mim no Express 4.Express ^4.16.2
Nenhuma das respostas existentes cumpre o que o OP pediu originalmente, que é substituir o Reason-Phrase padrão (o texto que aparece imediatamente após o código de status) enviado pelo Express.
O que você quer é
res.statusMessage
. Isso não faz parte do Express, é uma propriedade do objeto http.Response subjacente no Node.js 0.11+.Você pode usá-lo assim (testado no Express 4.x):
function(req, res) { res.statusMessage = "Current password does not match"; res.status(400).end(); }
Em seguida, use
curl
para verificar se 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
fonte
statusMessage
para algo diferente da mensagem padrão mapeada para o StatusCoderes.nativeResponse.statusMessage
No lado do servidor (middleware Express):
if(err) return res.status(500).end('User already exists.');
Lidar com o 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); } });
fonte
Uma maneira elegante de lidar com erros personalizados como este no expresso é:
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); }
(você também pode usar express ' express.errorHandler embutido para isso)
Então, em seu middleware, antes de suas rotas:
Então, onde você deseja criar o erro 'A senha atual não corresponde':
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); }
fonte
Você pode usar assim
return res.status(400).json({'error':'User already exists.'});
fonte
Meu caso de uso está enviando uma mensagem de erro JSON customizada, já que estou usando o expresso para alimentar minha API REST. Acho que esse é um cenário bastante comum, então vou me concentrar nele em minha resposta.
Versão curta:
Tratamento expresso de erros
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); } });
Eleve os erros de qualquer ponto do código, fazendo:
var JSONError = require('./JSONError'); var err = new JSONError(404, 'Uh oh! Can't find something'); next(err);
Versão longa
A maneira canônica de lançar erros é:
var err = new Error("Uh oh! Can't find something"); err.status = 404; next(err)
Por padrão, o Express lida com isso empacotando-o ordenadamente como uma resposta HTTP com o código 404 e o corpo consistindo na string de mensagem anexada a um rastreamento de pilha.
Isso não funciona para mim quando estou usando o Express como um servidor REST, por exemplo. Desejo que o erro seja enviado de volta como JSON, não como HTML. Eu também definitivamente não quero que meu rastreamento de pilha seja transferido para meu cliente.
Posso enviar JSON como resposta usando
req.json()
, por exemplo. algo parecidoreq.json({ status: 404, message: 'Uh oh! Can't find something'})
. Opcionalmente, posso definir o código de status usandoreq.status()
. Combinando os dois:req.status(404).json({ status: 404, message: 'Uh oh! Can't find something'});
Isso funciona como um encanto. Dito isso, acho bastante difícil digitar sempre que ocorre um erro, e o código não é mais autodocumentado como o nosso
next(err)
. Parece muito semelhante a como uma resposta JSON normal (ou seja, válida) é enviada. Além disso, quaisquer erros lançados pela abordagem canônica ainda resultam em saída HTML.É aqui que entra o middleware de tratamento de erros do Express. Como parte de minhas rotas, eu defino:
app.use(function(err, req, res, next) { console.log('Someone tried to throw an error response'); });
Eu também faço a subclasse de Error em uma classe 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;
Agora, quando quero lançar um erro no código, eu faço:
var err = new JSONError(404, 'Uh oh! Can't find something'); next(err);
Voltando ao middleware de tratamento de erros personalizado, eu o modifico para:
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); } }
Subclassificar o erro em JSONError é importante, pois suspeito que o Express faz uma
instanceof Error
verificação no primeiro parâmetro passado para anext()
para determinar se um manipulador normal ou um manipulador de erro deve ser invocado. Posso remover ainstanceof JSONError
verificação e fazer pequenas modificações para garantir que erros inesperados (como uma falha) também retornem uma resposta JSON.fonte
Ao usar o Axios, você pode recuperar a mensagem de resposta personalizada com:
Axios.get(“your_url”) .then(data => { ... do something }.catch( err => { console.log(err.response.data) // you want this })
... depois de defini-lo no Express como:
res.status(400).send(“your custom message”)
fonte
Se o seu objetivo é apenas reduzi-lo a uma linha única / simples, você pode confiar um pouco nos padrões ...
return res.end(res.writeHead(400, 'Current password does not match'));
fonte
Bem, no caso do Restify, devemos usar o
sendRaw()
métodoA sintaxe é:
res.sendRaw(200, 'Operation was Successful', <some Header Data> or null)
fonte