ホームページ  >  記事  >  ウェブフロントエンド  >  Expressミドルウェアの仕組みとその実装原理を分析する

Expressミドルウェアの仕組みとその実装原理を分析する

巴扎黑
巴扎黑オリジナル
2017-09-01 10:18:42978ブラウズ

この記事では、主に Express ミドルウェアの仕組みと実装原理を紹介します。編集者がそれを紹介し、参考にさせていただきます。エディターをフォローして見てみましょう

はじめに

ミドルウェアメカニズムを使用すると、特定のプロセスに処理ステップを追加することができ、それによってプロセスの入力または出力に影響を与えたり、中間効果、ステータス、またはこのプロセスを傍受します。ミドルウェアのメカニズムは Tomcat のフィルターに似ており、どちらも責任連鎖モデルの特定の実装です。

エクスプレスミドルウェアの使用例


let express = require('express')
let app = express()
//解析request 的body
app.use(bodyParser.json())
//解析 cookie
app.use(cookieParser())
//拦截
app.get('/hello', function (req, res) {
 res.send('Hello World!');
});

ミドルウェアメカニズムをシミュレートし、解析リクエストを実装するミドルウェアをシミュレートします

最初にリクエストをシミュレートしますrequest


request = { //模拟的request
  requestLine: 'POST /iven_ HTTP/1.1',
  headers: 'Host:www.php.cn\r\nCookie:BAIDUID=E063E9B2690116090FE24E01ACDDF4AD:FG=1;BD_HOME=0',
  requestBody: 'key1=value1&key2=value2&key3=value3',
}

一个http请求分为请求行、请求头、和请求体,这三者之间通过rnrn即一个空行来分割,这里假设已经将这三者分开,requestLine(请求行)中有方法类型,请求url,http版本号,这三者通过空格来区分,headers(请求头)中的各部分通过rn来分割,requestBody

function App() {
  if (!(this instanceof App))
    return new App();
  this.init();
}
App.prototype = {
  constructor: App,
  init: function() {
    this.request = { //模拟的request
      requestLine: 'POST /iven_ HTTP/1.1',
      headers: 'Host:www.php.cn\r\nCookie:BAIDUID=E063E9B2690116090FE24E01ACDDF4AD:FG=1;BD_HOME=0',
      requestBody: 'key1=value1&key2=value2&key3=value3',
    };
    this.response = {}; //模拟的response
    this.chain = []; //存放中间件的一个数组
    this.index = 0; //当前执行的中间件在chain中的位置
  },
  use: function(handle) { //这里默认 handle 是函数,并且这里不做判断
    this.chain.push(handle);
  },
  next: function() { //当调用next时执行index所指向的中间件
    if (this.index >= this.chain.length)
      return;
    let middleware = this.chain[this.index];
    this.index++;
    middleware(this.request, this.response, this.next.bind(this));
  },
}
http リクエストは、リクエストライン、リクエストヘッダ、リクエストボディに分かれており、これら 3 つは rnrn、つまり空行で区切られているものとします。 requestLine (リクエスト行) にはメソッドタイプ、リクエスト URL、http バージョン番号が含まれており、これら 3 つは headers (リクエストヘッダー) で区切られています。 ) rn で分割され、パラメータは requestBody (リクエストボディ) の & で区別されます

ミドルウェアメカニズムをシミュレートします


ミドルウェアは関数を実行し、リクエスト、レスポンス、次の 3 つのパラメータを受け入れます

 function lineParser(req, res, next) {
    let items = req.requestLine.split(' ');
    req.methond = items[0];
    req.url = items[1];
    req.version = items[2];
    next(); //执行下一个中间件
  }

function headersParser(req, res, next) {
  let items = req.headers.split('\r\n');
  let header = {}
  for(let i in items) {
    let item = items[i].split(':');
    let key = item[0];
    let value = item[1];
    header[key] = value;
  }
  req.header = header;
  next(); //执行下一个中间件
}

function bodyParser(req, res, next) {
  let bodyStr = req.requestBody;
  let body = {};
  let items = bodyStr.split('&');
  for(let i in items) {
    let item = items[i].split('=');
    let key = item[0];
    let value = item[1];
    body[key] = value;
  }
  req.body = body;
  next(); //执行下一个中间件
}

function middleware3(req, res, next) {
  console.log('url: '+req.url);
  console.log('methond: '+req.methond);
  console.log('version: '+req.version);
  console.log(req.body);
  console.log(req.header);
  next(); //执行下一个中间件
}


リクエスト処理用のミドルウェア


let app = App();
app.use(lineParser);
app.use(headersParser);
app.use(bodyParser);
app.use(middleware3);
app.next();

テストコード


function App() {
  if (!(this instanceof App))
    return new App();
  this.init();
}
App.prototype = {
  constructor: App,
  init: function() {
    this.request = { //模拟的request
      requestLine: 'POST /iven_ HTTP/1.1',
      headers: 'Host:www.php.cn\r\nCookie:BAIDUID=E063E9B2690116090FE24E01ACDDF4AD:FG=1;BD_HOME=0',
      requestBody: 'key1=value1&key2=value2&key3=value3',
    };
    this.response = {}; //模拟的response
    this.chain = []; //存放中间件的一个数组
    this.index = 0; //当前执行的中间件在chain中的位置
  },
  use: function(handle) { //这里默认 handle 是函数,并且这里不做判断
    this.chain.push(handle);
  },
  next: function() { //当调用next时执行index所指向的中间件
    if (this.index >= this.chain.length)
      return;
    let middleware = this.chain[this.index];
    this.index++;
    middleware(this.request, this.response, this.next.bind(this));
  },
}
function lineParser(req, res, next) {
    let items = req.requestLine.split(' ');
    req.methond = items[0];
    req.url = items[1];
    req.version = items[2];
    next(); //执行下一个中间件
  }

function headersParser(req, res, next) {
  let items = req.headers.split('\r\n');
  let header = {}
  for(let i in items) {
    let item = items[i].split(':');
    let key = item[0];
    let value = item[1];
    header[key] = value;
  }
  req.header = header;
  next(); //执行下一个中间件
}

function bodyParser(req, res, next) {
  let bodyStr = req.requestBody;
  let body = {};
  let items = bodyStr.split('&');
  for(let i in items) {
    let item = items[i].split('=');
    let key = item[0];
    let value = item[1];
    body[key] = value;
  }
  req.body = body;
  next(); //执行下一个中间件
}

function middleware3(req, res, next) {
  console.log('url: '+req.url);
  console.log('methond: '+req.methond);
  console.log('version: '+req.version);
  console.log(req.body);
  console.log(req.header);
  next(); //执行下一个中间件
}
let app = App();
app.use(lineParser);
app.use(headersParser);
app.use(bodyParser);
app.use(middleware3);
app.next();

全体のコード


りー

走る結果


上記のコード全体を実行すると、次の情報が出力されます🎜🎜🎜🎜
url: /iven_
methond: POST
version: HTTP/1.1
{key1: "value1", key2: "value2", key3: "value3"}
{Host: "www.php.cn", Cookie: "BAIDUID=E063E9B2690116090FE24E01ACDDF4AD"}

以上がExpressミドルウェアの仕組みとその実装原理を分析するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。