欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈express 中间件机制及实现原理

程序员文章站 2022-05-14 19:08:32
简介 中间件机制可以让我们在一个给定的流程中添加一个处理步骤,从而对这个流程的输入或者输出产生影响,或者产生一些中作用、状态,或者拦截这个流程。中间件机制和tomca...

简介

中间件机制可以让我们在一个给定的流程中添加一个处理步骤,从而对这个流程的输入或者输出产生影响,或者产生一些中作用、状态,或者拦截这个流程。中间件机制和tomcat的过滤器类似,这两者都属于责任链模式的具体实现。

express 中间件使用案例

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 = { //模拟的request
  requestline: 'post /iven_ http/1.1',
  headers: 'host:www.baidu.com\r\ncookie:baiduid=e063e9b2690116090fe24e01acddf4ad:fg=1;bd_home=0',
  requestbody: 'key1=value1&key2=value2&key3=value3',
}

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

模拟中间件机制

约定 中间件一定是一个函数并且接受 request, response, 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.baidu.com\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));
  },
}

对 request 处理的中间件

 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.baidu.com\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.baidu.com", cookie: "baiduid=e063e9b2690116090fe24e01acddf4ad"}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。