Express中間部品のbody-parserの原理分析


原文を読む
前言ExpressはNodeJSプラットフォームのWebフレームワークに基づいており、広く応用されており、Expressコミュニティには多くの開発者がExpressミドルウェアの特性を通して、様々な機能のミドルウェアを開発し、いくつかの応答を処理し、要求対象req、応答オブジェクトresに属性または方法を追加している.次に、よく使われるbody-parserミドルウェアの原理を分析して、Expressミドルウェアの開発方法を調べます.もっと知りたいなら、Expressの内部パッケージの原理は「Expressソース分析と簡易パッケージ」を見られます.
body-parserの基本使用
中間部品の原理を分析したいのですが、まず使用から着手し、用法を十分に理解した上で分析し、今は簡単なExpressサービスを構築し、body-parser中間部品を使用して、使用前にインストールしなければなりません.
npm install express body-parser
body-parserコードを使うと以下の通りです.
const express = require("express");
const bodyParser = require("body-parser");

//     
const app = express();

//    body-parser   
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

//     
app.post("/login", function (req, res) {
    console.log(req.body);
    res.send(req.body);
});

//     
app.listen(3000, function () {
    console.log("server start 3000");
});
上記のサーバを起動し、postmanツールによりそれぞれフォーム提出とjsonのフォーマットでアクセスする.http://localhost:3000/loginサーバ制御バックグラウンドの印刷結果とpostmanの返却結果を確認する.
body-parserの実現
1、原理分析
上の使用例から私達はいくつかの点を分析できます.
  • まず、body-parserのミドルウェアの役割は、reqに属性bodyを追加し、値を対象として、要求体のパラメータをキーペアの形で記憶することである.
  • に次いで、body-parserは、POSTからの要求のみを処理する.
  • 最後に、body-parserモジュールは、フォーム提出およびurlencodedフォーマットの要求体パラメータをそれぞれ処理する2つの方法jsonおよびjsonがあるオブジェクトを導出する.
  • 2、urlencoded、json公共ロジックを分析する
    実現する前に、まず二つの方法を分析してみます.まず、要求体の内容を読み取る必要があります.データ伝送のタイプはバッファerです.文字列に変換した後、提出方法によって、要求体の内容は照会文字列またはjson文字列の違いが生じます.
    解析に失敗した場合は、エラー処理が必要であり、POSTの要求でない場合は、他のミドルウェアを下方に実行する必要があり、最もコアなことは、要求体のデータをオブジェクトに変換してreq.bodyにかけることである.
    使用する変換データの方法は、一意の違いであり、両者を区別することができるのは、要求ヘッダContent-Typeの値であるので、すべての共通論理を抽出して、一つのacceptPost関数で実行することができる.
    3、モジュールの作成
    私達は以下に自分のbody-parserモジュールを作って、命名衝突を防止します.私達のモジュールはmy-body-parserと名づけました.処理パラメータはquerystringqsの二つのモジュールを使用する必要があります.
    npm install qsqsqsは、基本的に同じ役割を果たしています.クエリー文字列フォーマットのパラメータを処理していますが、ちょっとした違いがあります.querystringは1つのレベルしか処理できません.querystringは複数のレベルを処理できます.
    const querystring = require("querystring");
    const qs = require("qs");
    
    // urlencoded   json     
    function acceptPost() {
        // ...
    }
    
    //          
    function urlencoded() {
        // ...
    }
    
    //       json    
    function json() {
        // ...
    }
    
    //     
    module.exports = { urlencoded, json };
    基本モジュールを構築した後、qsモジュール内の共通論理関数body-parserを実装します.
    4、acceptPostの実現acceptPost方法とurlencoded方法を両立させるために、二つのパラメータを設計した.一つは、現在の起動方法を区別するjsonであり、一つはtype方法に対するurlencodedである.
    // acceptPost    
    // urlencoded     json          
    function acceptPost(type, options) {
        //          
        return function (req, res, next) {
            //      
            let contentType = req.headers["content-type"];
    
            //                           
            if (
                contentType === "application/x-www-form-urlencoded" ||
                contentType === "application/json"
            ) {
                //        
                let buffers = [];
    
                req.on("data", function (data) {
                    //           
                    buffers.push(data);
                });
    
                req.on("end", function () {
                    //            
                    let result = Buffer.concat(buffers).toString();
    
                    //         req.body    
                    //            querystring   qs,     JSON.parse
                    if (type === "form") {
                        //      extended    true    qs,     querystring
                        req.body = options.extended ? qs.parse(result) : querystring.parse(result);
                    } else if(type === "json") {
                        req.body = JSON.parse(result);
                    }
    
                    next(); //     
                });
    
                //     
                req.on("err", function (err) {
                    next(err);
                });
            } else {
                next();
            }
        }
    }
    5、urlencodedとjson方法の実現
    //          
    function urlencoded(options) {
        //    type  
        let type = "form";
        return acceptPost(type, options)
    }
    
    //       json    
    function json() {
        //    type  
        let type = "json";
        return acceptPost(type);
    }
    すべての共通論理を抽出した後、options及びurlencodedの方法の内部では、異なるタイプを定義するだけで中間論理を実行することができることがわかった.
    締め括りをつける
    上記の解析jsonミドルウェアの原理は、body-parseミドルウェア開発のモードを理解することを目的としています.ここでまとめてみると、Expressミドルウェアは、関数であり、Expressreqresnextを返します.nextに内蔵されているエラー処理ミドルウェアに引き渡され、ミドルウェア内部コードが非同期動作に関連する場合、非同期完了のコール中にnextを呼び出す必要があり、これはExpressに及ばない便利な点であると同時に、両者の違いでもある.