Node / express'te özel bir http durum mesajı nasıl gönderilir?


90

Node.js uygulamam, express / samples / mvc uygulaması gibi modellenmiştir .

Bir denetleyici eyleminde, özel bir http mesajıyla bir HTTP 400 durumu ortaya çıkarmak istiyorum. Varsayılan olarak http durum mesajı "Kötü İstek" dir:

HTTP/1.1 400 Bad Request

Ama göndermek istiyorum

HTTP/1.1 400 Current password does not match

Çeşitli yollar denedim ama hiçbiri http durum mesajını özel mesajıma ayarlamadı.

Mevcut çözüm denetleyici işlevim şöyle görünüyor:

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;
  } 
  // ...
}

Her şey yolunda gidiyor ama ... bunu yapmanın doğru yolu değil gibi görünüyor.

Ekspres kullanarak http durum mesajını ayarlamanın daha iyi bir yolu var mı?


4
Görünüşe göre bu tek çözüm yolu. Ancak böyle bir şey tavsiye etmem, HTTP 1.1 spesifikasyonunun bazı iyi nedenlerden dolayı standartlaştırılmış hata açıklaması vardır. İyi bilinen durum kodlarını özel açıklamalarla göndermenin kötü bir uygulama olduğunu düşünüyorum, ancak bu size kalmış.
schaermu

Hmmm - belki bu doğru. Öte yandan, tarayıcıların sadece durum kodunu kontrol ettiğini ve insan tarafından okunabilir http durum mesajını kontrol etmediğini varsayıyorum. Varsa somut (yani varsayılan olmayan) bir hata mesajını taşımak için http durum mesajını kullanmanın iyi bir fikir olduğunu düşündüm. Artı, istemci tarafı java betiğini kullanarak elde etmek kolay (jQuery kullanarak, hatayı görüntüleme amacıyla almak için "jqXHR.statusText" yapabilirsiniz)
lgersman

4
Uyumluluk veya olası tarayıcı sorunları ile ilgili değil, sadece kötü bir uygulamadır;) görüntülenmek üzere bir hata mesajı istiyorsanız, bunu gövde olarak gönderin, amaçlanan amaç budur.
schaermu

6
Belirli hata açıklamaları spesifikasyonun parçası değildir. RCF-2616 özellikle şunları belirtir: "HTTP / 1.1 için tanımlanan sayısal durum kodlarının ayrı değerleri ve karşılık gelen Sebep-İfadelerinin örnek bir kümesi aşağıda sunulmuştur. Burada listelenen neden ifadeleri yalnızca önerilerdir - protokolü etkilemeden yerel eşdeğerler. "
Ted Bigham

Özel neden ifadeleri harikadır, ancak (mesajınız "Mevcut şifre eşleşmiyor" "olduğundan), aslında burada 401 kodunu istiyormuşsunuz gibi görünüyor, bu durumda muhtemelen mesajı değiştirmeniz gerekmeyecektir.
Codebling

Yanıtlar:


60

Ayrıntılar için bu res.send(400, 'Current password does not match') Look express 3.x belgelerine bakabilirsiniz.

Expressjs 4.x için GÜNCELLEME

Bu şekilde kullanın ( express 4.x belgelerine bakın ):

res.status(400).send('Current password does not match');
// or
res.status(400);
res.send('Current password does not match');

41
maalesef bu http durum mesajını ayarlamayacak, ancak gövde içeriği olarak 'Mevcut şifre eşleşmiyor' gönderecek ...
lgersman

Bu, HTTP durumunu ayarlar, ancak bu yöntem imzası kullanımdan kaldırıldığı için bir uyarı verir.
null atanabilirlik

1
res.status(400).send('Current password does not match');Örnek Express 4 benim için çalışıyor
Tyler Collier

ÇalışıyorExpress ^4.16.2
Ajay

105

Mevcut cevapların hiçbiri OP'nin orijinal olarak istediği şeyi yerine getirmiyor, bu da Express tarafından gönderilen varsayılan Sebep-Cümle'yi (durum kodunun hemen ardından görünen metin) geçersiz kılmaktır .

İstediğin şey res.statusMessage. Bu Express'in bir parçası değildir, Node.js 0.11+ içindeki temel http.Response nesnesinin bir özelliğidir.

Bunu şu şekilde kullanabilirsiniz (Express 4.x'te test edilmiştir):

function(req, res) {
    res.statusMessage = "Current password does not match";
    res.status(400).end();
}

Daha sonra curlçalıştığını doğrulamak için kullanın :

$ 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

6
Bu, statusMessage
Durum Koduna

4
Mülkü temeldeki nesneden alabilirsinizres.nativeResponse.statusMessage
sebilasse

@RobertMoskal Minimal bir Express sunucu (Express 4.16.1 ve Node 12.9.0) kullanılarak test edildi ve benim için hala çalışıyor. Uygulama kodunuzu kontrol edin: belki başka bir sorun olabilir.
mamacdon

Bunun neden kabul edilen cevap olmadığından emin değilim, çünkü en azından bunu yazarken kesinlikle çözüm bu.
Aaron Summers

1
Bu, değil HTTP2 HTTP1.1 için çalışmalıdır nodejs.org/dist/latest-v15.x/docs/api/...
Jokesterfr

12

Sunucu tarafında (Ekspres ara katman yazılımı):

if(err) return res.status(500).end('User already exists.');

İstemci tarafında tutun

Açısal:-

$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);
    }
});

11

Ekspres olarak buna benzer özel hataları işlemenin zarif bir yolu şudur:

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);
}

(bunun için express 'yerleşik express.errorHandler'ı da kullanabilirsiniz )

Sonra ara yazılımınızda, rotalarınızdan önce:

app.use(errorHandler);

Ardından, 'Mevcut şifre eşleşmiyor' hatasını oluşturmak istediğiniz yerde:

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);
}

err.status = 400; daha yaygın olduğuna inanıyorum.
mkmelin

11

Bunu böyle kullanabilirsin

return res.status(400).json({'error':'User already exists.'});

3

Kullanım durumum, REST API'mi güçlendirmek için ekspres kullandığım için özel bir JSON hata mesajı gönderiyor. Bunun oldukça yaygın bir senaryo olduğunu düşünüyorum, bu yüzden cevabımda buna odaklanacağım.

Kısa versiyon:

Ekspres Hata İşleme

Hata işleme ara yazılımını, özellikle imza ile (err, req, res, next) üç yerine dört bağımsız değişken dışında diğer ara yazılımlar gibi tanımlayın. ... Hata işleme ara yazılımını en son, diğer app.use () kullanımından sonra tanımlar ve çağrıları yönlendirirsiniz

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);
    }
  });

Şunları yaparak koddaki herhangi bir noktadan hataları artırın:

var JSONError = require('./JSONError');
var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);

Uzun versiyon

Hataları atmanın kanonik yolu şudur:

var err = new Error("Uh oh! Can't find something");
err.status = 404;
next(err)

Varsayılan olarak, Express bunu, 404 kodlu bir HTTP Yanıtı olarak düzgün bir şekilde paketleyerek ve bir yığın izleme eklenmiş mesaj dizesinden oluşan bir gövdeyle ele alır.

Örneğin, Express'i bir REST sunucusu olarak kullandığımda bu benim için çalışmıyor. Hatanın HTML olarak değil, JSON olarak geri gönderilmesini istiyorum. Ayrıca yığın izimin müşterime taşınmasını da kesinlikle istemiyorum.

JSON'ı req.json()örneğin kullanarak yanıt olarak gönderebilirim . gibi bir şey req.json({ status: 404, message: 'Uh oh! Can't find something'}). İsteğe bağlı olarak, ile durum kodunu ayarlayabilirim req.status(). İkisini birleştirmek:

req.status(404).json({ status: 404, message: 'Uh oh! Can't find something'});

Bu bir cazibe gibi çalışıyor. Bununla birlikte, her hata aldığımda yazmayı oldukça güç buluyorum ve kod artık bizimki gibi kendi kendini belgelemiyor next(err). Normal (yani geçerli) bir JSON yanıtının gönderilme şekline çok benziyor. Ayrıca, kanonik yaklaşım tarafından atılan tüm hatalar yine de HTML çıktısıyla sonuçlanır.

Express'in hata işleme ara yazılımı burada devreye girer. Rotalarımın bir parçası olarak şunları tanımlarım:

app.use(function(err, req, res, next) {
    console.log('Someone tried to throw an error response');
  });

Ayrıca Error sınıfını özel bir JSONError sınıfına alıyorum:

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;

Şimdi, koda bir Hata atmak istediğimde, şunu yapıyorum:

var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);

Özel hata işleme ara yazılımına geri dönersek, bunu şu şekilde değiştiriyorum:

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);
  }
}

Hatayı JSONError'a alt sınıflandırma önemlidir, zira Express'in normal bir işleyicinin mi yoksa bir hata işleyicinin mi çağrılması gerektiğini belirlemek instanceof Erroriçin a'ya geçirilen ilk parametre üzerinde bir kontrol yaptığından şüpheleniyorum next(). instanceof JSONErrorBeklenmeyen hataların (çökme gibi) ayrıca bir JSON yanıtı döndürmesini sağlamak için denetimi kaldırabilir ve küçük değişiklikler yapabilirim.


3

Axios'u kullanırken özel yanıt mesajını şu şekilde alabilirsiniz:

Axios.get(“your_url”)
.then(data => {
... do something
}.catch( err => {
console.log(err.response.data) // you want this
})

... Express'te şu şekilde ayarladıktan sonra:

res.status(400).send(“your custom message”)

çok basit, neden üstünüzdeki insanlar işleri bu kadar karmaşık hale getiriyor?
iqbal125

0

Amacınız sadece onu tek / basit bir çizgiye indirmekse, varsayılanlara biraz güvenebilirsiniz ...

return res.end(res.writeHead(400, 'Current password does not match'));

-2

Restify durumunda sendRaw()yöntemi kullanmalıyız

Sözdizimi: res.sendRaw(200, 'Operation was Successful', <some Header Data> or null)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.