ノード/エクスプレスでカスタムhttpステータスメッセージを送信するにはどうすればよいですか?


89

私のnode.jsアプリは、express / examples / mvcアプリのようにモデル化されています。

コントローラのアクションで、カスタムhttpメッセージを使用してHTTP400ステータスを吐き出したい。デフォルトでは、httpステータスメッセージは「BadRequest」です。

HTTP/1.1 400 Bad Request

でも送りたい

HTTP/1.1 400 Current password does not match

さまざまな方法を試しましたが、httpステータスメッセージをカスタムメッセージに設定する方法はありませんでした。

私の現在のソリューションコントローラー関数は次のようになります。

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

すべてが正常に機能しますが...それは正しい方法ではないようです。

Expressを使用してhttpステータスメッセージを設定するためのより良い方法はありますか?


4
まあ、これが唯一の回避策のようです。しかし、私はそのようなことをアドバイスしません。HTTP1.1仕様では、いくつかの正当な理由でエラーの説明が標準化されています。よく知られたステータスコードとカスタムの説明を送信するのは悪い習慣だと思いますが、それはあなた次第です。
schaermu 2013年

うーん-多分それは本当です。一方、ブラウザはステータスコードをチェックするだけで、人間が読めるhttpステータスメッセージはチェックしないと思います。可能な場合は、httpステータスメッセージを使用して具体的な(つまり、デフォルト以外の)エラーメッセージを転送することをお勧めします。さらに、クライアント側のjavaスクリプトを使用してそれを簡単に取得できます(jQueryを使用すると、「jqXHR.statusText」を実行して表示目的でエラーを取得できます)
lgersman 2013年

4
互換性や潜在的なブラウザの問題ではなく、悪い習慣です;)表示用のエラーメッセージが必要な場合は、本文として送信してください。これが目的です。
schaermu 2013年

6
特定のエラーの説明は仕様の一部ではありません。RCF-2616は、具体的に次のように述べています。「HTTP / 1.1用に定義された数値ステータスコードの個々の値、および対応する理由フレーズのセットの例を以下に示します。ここにリストされている理由フレーズは推奨事項にすぎません。プロトコルに影響を与えずにローカルで同等のもの。」
テッドビガム2015年

カスタム理由フレーズは素晴らしいですが、(メッセージが「現在のパスワードが一致しません」であるため)実際にここでコード401が必要なようです。この場合、メッセージを変更する必要はないでしょう。
コーディング2016年

回答:


59

詳細については、このres.send(400, 'Current password does not match') Look express3.xドキュメントを確認してください。

Expressjs4.xのアップデート

この方法を使用します(express 4.xドキュメントを参照):

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

41
残念ながら、これはhttpステータスメッセージを設定しませんが、本文の内容として「現在のパスワードが一致しません」を送信します...
lgersman 2013年

これはHTTPステータスを設定しますが、このメソッドシグネチャは非推奨であるため、警告をスローします。
無効性2014

1
res.status(400).send('Current password does not match');例は、Express 4のために私の作品
タイラーコリア

で働くExpress ^4.16.2
Ajay 2017

103

既存の回答はいずれも、OPが最初に要求したこと、つまりExpressによって送信されたデフォルトのReason-Phrase(ステータスコードの直後に表示されるテキスト)を上書きすることを実現していません。

あなたが欲しいのはres.statusMessageです。これはExpressの一部ではなく、Node.js0.11以降の基になるhttp.Responseオブジェクトのプロパティです。

このように使用できます(Express 4.xでテスト済み):

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

次に、を使用curlして機能することを確認します。

$ 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
これは、statusMessageStatusCodeにマップされた標準メッセージ以外のものに設定する正しい方法です
peteb 2016年

4
基になるオブジェクトのプロパティは、res.nativeResponse.statusMessage
次のコマンド

@RobertMoskal最小限のExpressサーバー(Express 4.16.1およびノー​​ド12.9.0)を使用してテストしましたが、それでも機能します。アプリケーションコードを確認してください。何か他の問題がある可能性があります。
mamacdon

少なくとも私がこれを書いている時点では、これが間違いなく解決策であるため、これが受け入れられた答えではない理由がわかりません。
アーロンサマーズ

12

サーバー側(Expressミドルウェア):

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

クライアント側のハンドル

角度:-

$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

Expressでこのようなカスタムエラーを処理する1つのエレガントな方法は次のとおりです。

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

(これには、expressの組み込みexpress.errorHandlerを使用することもできます)

次に、ミドルウェアで、ルートの前に:

app.use(errorHandler);

次に、エラーを作成する場所 '現在のパスワードが一致しません':

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; 私が信じているより一般的です。
mkmelin 2015


3

Expressを使用してRESTAPIを強化しているため、私のユースケースではカスタムJSONエラーメッセージを送信しています。これはかなり一般的なシナリオだと思うので、私の答えではそれに焦点を当てます。

短縮版:

Expressエラー処理

エラー処理ミドルウェアを他のミドルウェアと同じように定義しますが、3つではなく4つの引数、特に署名(err、req、res、next)を使用します。...エラー処理ミドルウェアを最後に定義し、他のapp.use()とルーティング呼び出しの後に

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

次の手順を実行して、コードの任意のポイントからエラーを発生させます。

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

ロングバージョン

エラーをスローする標準的な方法は次のとおりです。

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

デフォルトでは、Expressは、コード404とスタックトレースが追加されたメッセージ文字列で構成される本文を含むHTTP応答として適切にパッケージ化することでこれを処理します。

たとえば、ExpressをRESTサーバーとして使用している場合、これは機能しません。エラーをHTMLではなくJSONとして返送したいと思います。また、スタックトレースをクライアントに移動させたくないことも間違いありません。

req.json()たとえば、JSONを応答として送信できます。のようなものreq.json({ status: 404, message: 'Uh oh! Can't find something'})。オプションで、を使用してステータスコードを設定できますreq.status()。2つを組み合わせる:

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

これは魅力のように機能します。とはいえ、エラーが発生するたびに入力するのは非常に扱いにくく、コードは以前のように自己文書化されなくなりましnext(err)た。これは、通常の(つまり有効な)応答JSONが送信される方法と非常によく似ています。さらに、正規のアプローチによってスローされたエラーは、引き続きHTML出力になります。

ここで、Expressのエラー処理ミドルウェアが登場します。ルートの一部として、次のように定義します。

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

また、ErrorをカスタムJSONErrorクラスにサブクラス化します。

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;

ここで、コードでエラーをスローしたい場合は、次のようにします。

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

カスタムエラー処理ミドルウェアに戻り、次のように変更します。

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

エラーをJSONErrorにサブクラス化することは重要です。これは、Expressがにinstanceof Error渡された最初のパラメーターをチェックしてnext()、通常のハンドラーまたはエラーハンドラーを呼び出す必要があるかどうかを判断するためです。instanceof JSONErrorチェックを削除し、小さな変更を加えて、予期しないエラー(クラッシュなど)もJSON応答を返すようにすることができます。


2

Axiosを使用する場合、次のコマンドでカスタム応答メッセージを取得できます。

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

... Expressで次のように設定した後:

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

0

あなたの目標がそれを単一/単純な行に減らすことだけであるならば、あなたはデフォルトに少し頼ることができます...

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

-2

Restifyの場合は、メソッドを使用sendRaw()する必要があります

構文は次のとおりです。 res.sendRaw(200, 'Operation was Successful', <some Header Data> or null)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.