Site Overlay

泛业务后端-Express中间件

目的

熟悉Express框架,中间件是什么?手写中间件

Express作为Node框架提供了什么机制

  • 为不同 URL 路径中使用不同 HTTP 动词的请求(路由)编写处理程序。
  • 集成了“视图”渲染引擎,以便通过将数据插入模板来生成响应。
  • 设置常见 web 应用设置,比如用于连接的端口,以及渲染响应模板的位置。
  • 在请求处理管道的任何位置添加额外的请求处理“中间件”。

什么是中间件?

中间件的本质就是一个JS函数

bodyParser中间件在express不同版本中

  • Express3依赖于Connect,内置了部分中间件express.bodyParser
  • Express 4 不再依赖于 Connect,从其核心移除了所有内置的中间件(除了 express.static 函数)。中间件需要安装导入注册显示添加。

Express 3 中间件及其在 Express 4 中的对应组件:https://github.com/senchalabs/connect#middleware

运用bodyParser中间件的例子(Express4)

<form action="/register" method="POST">
  <input type="text" name="name">
  <input type="password" name="password">
  <button>注册</button>
</form>
const express = require('express');
const app = express();
const bodyParser = require('body-parser');

app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.get('/', (req, res) => {
  res.render('index');
})

app.post('/register', (req, res) => {
  console.log(req.headers);
  console.log(req.body);
  res.send('hello world');
})

app.listen(3000);
bodyParser实现原理

bodyParser核心就是根据content-type类型的不同进行不同的处理
content-type的一些类型:
1. text/plain
2. application/json
3. application/x-www-form-urlencoded

 
手写一个bodyParser

// index.js
const express = require('express');
const app = express();
const bodyParserTest = require('./middlewares/body-parser-test');

app.set("view engine", "ejs");
app.use(bodyParserTest());

app.get('/', (req, res) => {
  res.render('index');
})

app.post('/register', (req, res) => {
  console.log(req.body);
  res.send(`${req.body.name} register success`);
})

app.listen(3000);
// Body-parser-test.js
const querystring = require('querystring');

function bodyParserTest() {
  return (req, res, next) => {
    // 排除不需要请求体的请求
    if (!['POST', 'PUT', 'PATCH'].includes(req.method)) {
      return next();
    }
    const contentType = req.headers['content-type']?.split('; ');
    const arr = [];
    console.log(contentType);

    req.on('data', (buff) => {
      arr.push(buff);
    });

    req.on('end', () => {
      const chunks = Buffer.concat(arr);
      // 根据不同content-type处理不同数据
      switch (contentType?.[0]) {
        case 'text/plain':
          req.body = chunks.toString();
          break;
        case 'application/json':
          req.body = JSON.parse(chunks.toString());
          break;
        case 'application/x-www-form-urlencoded':
          req.body = querystring.parse(chunks.toString());
          break;
        default:
          req.body = {};
          break;
      }

      // 流转给下一个中间件处理
      next();
    });
  };
}

module.exports = bodyParserTest;

21fcbd95-fcc4-4073-a7f9-d9cbd0551a85

8331d410-d85b-447a-a604-75fa1eb17570