Node.jsミドルウェアの仕組みの詳細な説明

Node.jsミドルウェアの仕組みの詳細な説明

Express ミドルウェアとは何ですか?

  • ミドルウェアとは、文字通り、ソフトウェアの 1 つの層と別の層の間に配置するものを意味します。
  • Express ミドルウェアは、Express サーバーへのリクエストのライフサイクル中に実行される関数です。
  • 各ミドルウェアは、接続されているすべてのルートの HTTP リクエストと応答にアクセスできます。
  • さらに、ミドルウェアは HTTP リクエストを終了したり、 next を使用して別のミドルウェア関数に渡したりすることもできます。このミドルウェアの「連鎖」により、コードを区分化し、再利用可能なミドルウェアを作成できます。

Expressミドルウェアを作成するための要件

Express ミドルウェアを作成、使用、テストするには、いくつかのものをインストールする必要があります。まず、Node と npm が必要です。インストールされていることを確認するには、次を実行します。

npm -v && ノード -v

インストールされている Node と NPM のバージョンが表示されます。エラーが発生した場合は、Node をインストールする必要があります。すべての例は、Node バージョン 8 以降および NPM バージョン 5 以降で使用する必要があります。

この記事では Express バージョン 4.x を使用します。バージョン 3.x からバージョン 4.x への重大な変更があるため、これは重要です。

Express ミドルウェア: 基礎

まず、Express の最も基本的な組み込みミドルウェアを使用します。新しいプロジェクトを作成し、npm で初期化します...

npm 初期化
npm インストールエクスプレス --save

server.js を作成し、次のコードを貼り付けます。

定数 express = require('express');
express() は、定数です。

app.get('/', (req, res, next) => {
  res.send('ようこそお帰りなさい');
});

アプリをリッスンする(3000);

ミドルウェアはどのような問題を解決しますか?なぜそれを使うのですか?

Web サーバー上で Node.js と Express を使用して Web アプリケーションを実行していると仮定します。このアプリでは、一部のページでログインする必要があります。

Web サーバーがデータの要求を受信すると、Express はユーザーとユーザーが要求しているデータに関する情報を含む要求オブジェクトを提供します。 Express では、応答オブジェクトへのアクセスも提供され、Web サーバーがユーザーに応答する前にこれを変更できます。これらのオブジェクトは、多くの場合、req、res と短縮されます。

ミドルウェア関数は、関連する情報を使用して req オブジェクトと res オブジェクトを変更するのに最適な場所です。たとえば、ユーザーがログインすると、データベースからユーザーの詳細を取得し、その詳細を res.user に保存できます。

ミドルウェアの機能はどのようになっているのでしょうか?

非同期関数userMiddleware(req, res, next) {
    試す {
        const userData = await getUserData(req.params.id); // 下記の app.get を参照

        if(ユーザーデータ) {
                要求ユーザー = ユーザーデータ;
                次();
        }
    } キャッチ(エラー) {
        res.status(500).send(error.message); //適切なエラー処理に置き換える
    }
}

エラーが発生し、他のコードを実行したくない場合は、関数を呼び出さないでください。この場合は必ず応答を送信してください。そうしないと、クライアントはタイムアウトするまで応答を待機します。

var app = express();

//通常のルートハンドラ
app.get('/user/:id', userMiddleware, userController);

ミドルウェアチェーン

ミドルウェア配列内でミドルウェアを連鎖したり、複数の app.use 呼び出しを使用したりすることができます。

app.use(ミドルウェアA);
app.use(ミドルウェアB);
app.get('/', [ミドルウェアC, ミドルウェアD], ハンドラー);

Express がリクエストを受信すると、終了アクションが発生するまで、リクエストに一致する各ミドルウェアが初期化された順序で実行されます。

したがって、エラーが発生すると、エラーを処理するためのすべてのミドルウェアが、そのうちの 1 つが next() 関数呼び出しを呼び出さなくなるまで順番に呼び出されます。

Expressミドルウェアの種類

  • router.use などのルーターレベルのミドルウェア
  • 組み込みミドルウェア: express.static、express.json、express.urlencoded
  • エラー処理ミドルウェア、例: app.use(err, req, res, next)
  • bodyparser、cookieparserなどのサードパーティミドルウェア
  • ルーターレベルのミドルウェア
  • express.Router モジュール式のインストール可能なルーティング ハンドラーを作成するには、express.Router クラスを使用します。ルーター インスタンスは、完全なミドルウェアおよびルーティング システムです。 ログ記録や認証などにミドルウェアを使用できます。以下に示すように、ユーザーの最新のアクティビティを記録し、認証ヘッダーを解析し、それを使用して現在ログインしているユーザーを特定し、それを Request オブジェクトに追加します。この関数は、プログラムが要求を受信するたびに実行されます。エラーが発生した場合は、後続のミドルウェアやルート処理を呼び出さずに、応答を終了します。
var ルーター = express.Router()
router.use() および router.METHOD() 関数を使用して、ルーター レベルのミドルウェアを読み込みます。
次の例では、ルーターをモジュールとして作成し、その中にミドルウェア関数をロードし、いくつかのルートを定義し、メイン アプリ内のパスにルーター モジュールをマウントします。
var express = require('express');
var ルーター = express.Router();

// マウントパスのないミドルウェア関数。このコードはルータへのリクエストごとに実行されます
// ログ記録
非同期関数 logMiddleware (req, res, next) {
    試す {
         console.log(req.user.id、新しい日付());
     次();
    } キャッチ() {
        res.status(500).send(エラーメッセージ);
    }
}
// 認証
    非同期関数 checkAuthentication(req, res, next) => {
// トークンのヘッダーまたは URL パラメータまたは POST パラメータをチェックします
const トークン = req.body.token || req.query.token || req.headers['x-access-token'] || req.headers['authorization'];
      if (トークン) {
        試す {
            // 秘密を検証する
            req.decoded = jwt.verify(token, config.secret) を待機します

            checkUser = authenticateTokenHelper.getUserDetail(req); を待機します。

            // 問題がなければ、他のルートで使用するために保存します
                if (checkUser) {
                        req.user = req.decoded
                        次()
                } それ以外 {
                    res.status(403).json({ を返します。 
                    メッセージ: responseMessage.noAuthorized 
                    })
                }
        } キャッチ (エラー) {
            res.status(401).json({ メッセージ: responseMessage.invalidToken }) を返します
        }
  } それ以外 {
    // トークンがない場合
    res.status(400).json({ メッセージ: responseMessage.invalidRequest }) を返します
  }
}
ルーターのログミドルウェアを使用します。
    router.get('/user, checkAuthentication, ハンドラ);

組み込みミドルウェア

Express には、次のミドルウェア関数が組み込まれています。

  • express.static は、HTML ファイル、画像などの静的リソースを提供します。
  • express.json ペイロードは、受信したリクエストを JSON で解析します。
  • express.urlencoded は、URL エンコードされたペイロードを含む受信リクエストを解析します。

エラー処理ミドルウェア

エラー処理ミドルウェアは常に 4 つの引数 (err、req、res、next) を取ります。 4 つの引数を指定して、これをエラー処理ミドルウェア関数として識別する必要があります。次のオブジェクトを使用する必要がない場合でも、それを指定する必要があります。そうしないと、次のオブジェクトは通常のミドルウェアとして解釈され、エラーを処理できなくなります。基本的な署名は次のとおりです。

app.use(関数 (err, req, res, next) {
  コンソールエラー(err.stack)
  res.status(500).send('問題が発生しました!')
})

例1:

app.get('/users', (req, res, next) => {
  next(new Error('エラーを渡しています!'));
});
app.use((err, req, res, next) => {
  コンソールログ(エラー);    
  if(!res.headersSent){
    res.status(500).send(err.message);
  }
});

この場合、パイプラインの最後にあるエラー処理ミドルウェアがエラーを処理します。また、res.headersSent プロパティをチェックしたことにも気付くかもしれません。これは、応答のヘッダーがすでにクライアントに送信されているかどうかを確認するだけです。そうでない場合は、HTTP 500 ステータスとエラー メッセージをクライアントに送信します。

例2:

エラー処理ミドルウェアを連鎖させることもできます。通常、エラーの種類によって処理方法が異なります。

app.get('/users, (req, res, next) => {
  let err = new Error('見つかりませんでした。');
  エラー httpステータスコード = 404;
  次へ(エラー);
});

app.get('/user, (req, res, next) => {
  let err = new Error('申し訳ありませんが、それはできません、Dave。');
  エラー.httpステータスコード = 304;
  次へ(エラー);
});

app.use((err, req, res, next) => {
   // 見つからないエラーを処理する
  (エラーhttpステータスコード === 404)の場合{
    res.status(400).render('見つかりません');
  }
   // 不正なエラーを処理する 
  そうでない場合(err.httpStatusCode === 304){
    res.status(304).render('権限がありません');
  }
    // すべてをキャッチ
   そうでない場合 (!res.headersSent) {
     res.status(err.httpStatusCode || 500).render('UnknownError');
  }
  次へ(エラー);
});
  • この場合、ミドルウェアは 404 (見つかりません) エラーがスローされたかどうかを確認します。そうである場合は、「NotFound」テンプレート ページをレンダリングし、ミドルウェア内の次の項目にエラーを渡します。
  • 次のミドルウェアは、304 (不正) エラーがスローされたかどうかを確認します。そうである場合は、「Unauthorized」ページをレンダリングし、パイプラインの次のミドルウェアにエラーを渡します。
  • 最後に、「catch all」エラー処理は単にエラーをログに記録し、応答が送信されない場合、間違った httpStatusCode (または何も提供されていない場合は HTTP 500 ステータス) を送信し、「UnknownError」テンプレートをレンダリングします。

サードパーティミドルウェア

場合によっては、バックエンドに追加機能を追加することもあります。必要な機能を取得するには Node.js モジュールをインストールし、アプリケーション レベルまたはルーター レベルでアプリケーションにロードします。

例: body-parser が Content-Type リクエスト ヘッダーを処理すると、すべてのミドルウェアは解析された本文を req.body プロパティに入力します。

定数 express = require('express');
bodyParser は、'body-parser' を必要とします。
express() は、定数です。
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
app.post('/save',(req,res)=>{
    res.json({
        "ステータス":true,
         「ペイロード」:req.body
    })
}
app.listen(3000,(要求,res)=>{
    console.log('ポートでサーバーが実行中')
})

要約する

ミドルウェア関数は、すべてのリクエストまたは特定のルートのすべてのリクエストでコードを実行し、リクエストまたは応答データに対してアクションを実行するのに最適な方法です。ミドルウェアは現代の Web サーバーの重要な部分であり、非常に便利です。

上記は、Node.js ミドルウェアの仕組みについての詳しい説明です。Node.js ミドルウェアの詳細については、123WORDPRESS.COM の他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • Nodejs の Express でよく使われるミドルウェア body-parser の解析
  • Node.js の Express ミドルウェアの詳細な理解
  • Node.js で画像を処理するミドルウェア、node-images の詳細な説明
  • Nodejs 開発 - 高速ルーティングとミドルウェア
  • NodeJS 学習ノート: Connect ミドルウェア アプリケーションの例
  • NodeJS 学習ノート: ミドルウェア モジュールの接続 (パート 2)
  • NodeJS 学習ノート: ミドルウェア モジュールの接続 (I)
  • Nodejs はブラックリストミドルウェア設計を実装します
  • node.js ミドルウェア express-session の使い方の詳しい説明

<<:  MySQL で datetime 型のデフォルト値を設定する方法

>>:  プライベートDockerリポジトリであるHarborをインストールするための詳細な手順

推薦する

指定フィールドによるMySQLカスタムリストのソートの実装

問題の説明ご存知のとおり、MySQL でフィールドを昇順に並べ替える SQL は次のとおりです (i...

Linux mpstat コマンドの使用方法の詳細な説明

1. mpstatコマンド1.1 コマンド形式 mpstat [ -A ] [ -u ] [ -V ...

Centos7 への mysql8.0rpm のインストール チュートリアル

まず、図をダウンロードしてください 1. まず、centos7に付属しているmariadbをアンイン...

複数の例で HTML フォームを使用する方法

参考までに、HTMLフォームの使い方を9つの簡単な例で分析します。具体的な内容は次のとおりです。 1...

Tomcat が応答データグラムを書き戻すタイミングの詳細な分析

疑問が生じるこの質問は、ファイルのダウンロードを記述しているときに発生しました。HttpServle...

CSS シャドウ効果の比較: ドロップシャドウとボックスシャドウ

Drop-shadow と box-shadow はどちらも影効果(ハロー効果)のための CSS プ...

MySQL 5.6.37 (zip) ダウンロード インストール 構成 グラフィック チュートリアル

この記事では、MySQL 5.6.37のダウンロード、インストール、設定のチュートリアルを参考までに...

よく使われるLinuxコマンド「ll」が無効、またはコマンドが見つからないという問題を解決します

質問:よく使用されるコマンド「ll」が無効であるか、コマンドが見つかりません理由: 「ll」コマンド...

JavaScript offsetParent のケーススタディ

1. offsetParentの定義: offsetParentは子要素に最も近い位置に配置された親...

MySQL インデックスの長所と短所、およびインデックス作成のガイドライン

1. インデックスを作成する理由(メリット)インデックスを作成するとシステムのパフォーマンスが大幅に...

Tomcat maxPostSize設定実装プロセス分析

1. maxPostSize を設定する理由は何ですか? tomcat コンテナには送信データのサイ...

React Nativeはモニタリングジェスチャーの上下プル効果を実現します

React Native は、プルアップとプルダウンの監視ジェスチャを実装します。詳細なコアコードは...

圧縮パッケージを使用して Linux 環境に JDK 13 をインストールする方法

JDK とは何ですか?まあ、この質問がわからないのであれば、なぜこれをインストールするのか本当にわか...

Navicat の MySQL へのリモート接続の実装手順の分析

序文皆さんはリモート サーバーで開発を行っており、MySQL の使用率はかなり高いはずです。コマンド...