nodejs article express (2) middleware detailed explanation

foreword

insert image description here

In the previous article, I briefly introduced the use of express.js, nodejs article express(1) , which mentioned the use of express middleware. In fact, in the process of project development, the role of middleware is ubiquitous in the server built with express.js.

For different application scenarios and different calling methods, middleware can be divided into the following categories: application-level middleware, routing-level middleware, error handling middleware, built-in middleware, and third-party middleware. After finishing the study, you will be able to use express middleware with ease.

Application level middleware

global middleware

The scope of action of this type of middleware includes all interfaces of the entire server. It does not care about the specific routing of the request, nor does it care about the method of the request. As long as the requested server address and port number are correct, the middleware function will be executed.

example

var express = require("express");
var APP = express();
var PORT = 3000;

function getOriginalUrl() {
    
    
  return function (req, res, next) {
    
    
    console.log(req.originalUrl);
    next();
  }
}

APP.use(getOriginalUrl());

APP.post("/api", function (req, res) {
    
    
  res.set("Content-Type", "application/json");
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

APP.get("/user/:id", function (req, res) {
    
    
  res.set("Content-Type", "application/json");
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

As shown in the above code, regardless of whether the client requests api or user/:id, the getOriginalUrl method will be called to print out the requested route.

Middleware that limits the request path

Function encapsulation processing for a specific path that meets a certain rule.

var express = require("express");
var APP = express();
var PORT = 3000;

function getParams() {
    
    
  return function (req, res, next) {
    
    
    console.log(`动态路由`, req.params);
    next();
  };
}

// 只针对路径是/user/:id的中间件
APP.use("/user/:id", getParams());

APP.get("/user/:id", function (req, res) {
    
    
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

The above example is only for middleware whose path is /user/:id. Of course, the first parameter of the use function can not only pass a string, but also pass a regex, and the middleware will be executed as long as it meets the requirements.

Middleware that limits the request method and request path

This is the most common way to use middleware

var express = require("express");
var app = express();
var port = 3000;

// express.json 就是中间件,用来处理客户端发送json数据在body中接收
app.post("/api", express.json(), function (req, res) {
    
    
  console.log(req.body)
  res.set("Content-Type", "application/json");
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

app.listen(port, function () {
    
    
  console.log("server runing at 3000");
});

multiple processing middleware

The global middleware described above, or the middleware that defines the request path, or the middleware that defines the request path and request method, can pass in multiple middleware at one time. After the execution of next(), these middleware can be chained in turn.

var express = require("express");
var APP = express();
var PORT = 3000;

function getOriginalUrl() {
    
    
  return function (req, res, next) {
    
    
    console.log(req.originalUrl, req.body);
    next();
  };
}

function setContentType(type) {
    
    
  return function(req,res,next) {
    
    
    res.set("Content-Type", type);
    next()
  }
}

// 全局使用多个中间件示例
APP.use(express.json(), getOriginalUrl(), setContentType("application/json"));

// 限定路径使用多个中间件示例
APP.use("/user/:id", express.json(), getOriginalUrl(), setContentType("application/json"));

// 限定路径和方法使用多个中间件示例
APP.get("/user/:id",express.json(), getOriginalUrl(), setContentType("application/json"), function (req, res) {
    
    
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

I feel that the above writing method is still a bit troublesome, we can simplify it

var express = require("express");
var APP = express();
var PORT = 3000;

function getOriginalUrl() {
    
    
  return function (req, res, next) {
    
    
    console.log(req.originalUrl, req.body);
    next();
  };
}

function setContentType(type) {
    
    
  return function(req,res,next) {
    
    
    res.set("Content-Type", type);
    next()
  }
}

var middlewares = [getOriginalUrl(), setContentType("application/json"), express.json()]

// 全局使用多个中间件示例
APP.use(middlewares);

// 限定路径使用多个中间件示例
APP.use("/user/:id", middlewares);

// 限定路径和方法使用多个中间件示例
APP.get("/user/:id", middlewares, function (req, res) {
    
    
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

If there are multiple middlewares, in some cases, I only want to execute the first two middlewares, but not the third middleware, how to deal with it?

function getOriginalUrl() {
    
    
  return function (req, res, next) {
    
    
    console.log(req.originalUrl, req.body);
    next();
  };
}

function setContentType(type) {
    
    
  return function (req, res, next) {
    
    
    res.set("Content-Type", type);
    // get请求时不接收前端传递过来的body参数,所以不需要处理客户端放在body中的json数据,也就是不需要express.json()
    if (req.method === "GET") {
    
    
      // 将会结束本次app.use的调用,跳过express.json()
      next("route");
    }
    next();
  };
}

var middlewares = [
  getOriginalUrl(),
  setContentType("application/json"),
  express.json(),
];

APP.use(middlewares);

Route-level middleware

Create a new router.js, the code is as follows

var express = require("express");

// 创建路由实例
const router = express.Router();

// 配置路由
router.get("/user/:id", function (req, res) {
    
    
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

router.delete("/user/:id", function (req, res) {
    
    
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

router.post("/user", function (req, res) {
    
    
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

// 导出路由
module.exports = router;

Introduce router in index.js and bind it

var express = require("express");
var APP = express();
var PORT = 3000;

var router = require('./router');

function getParams() {
    
    
  return function (req, res, next) {
    
    
    console.log(`动态路由`, req.params);
    next();
  };
}

APP.use("/user/:id", getParams());

// 挂载路由
APP.use(router)

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

Of course, if a series of paths all start with user, we can properly modify the following

router.js

var express = require("express");

// 创建路由实例
const router = express.Router();

// 配置路由
router.get("/:id", function (req, res) {
    
    
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

router.delete("/:id", function (req, res) {
    
    
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

router.post("/", function (req, res) {
    
    
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});

// 导出路由
module.exports = router;

index.js

var express = require("express");
var APP = express();
var PORT = 3000;

var router = require('./router');

function getParams() {
    
    
  return function (req, res, next) {
    
    
    console.log(`动态路由`, req.params);
    next();
  };
}

APP.use("/user/:id", getParams());

// 挂载路由
APP.use("/user", router);

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

The effect of the transformation is the same as before

error handling middleware

var express = require("express");
var APP = express();
var PORT = 3000;

APP.delete("/user/:id", function (req, res, next) {
    
    
  if (req.params.id === "0") {
    
    
    next({
    
    
      message: "该用户不存在"
    });
  }
  res.status("200");
  res.json({
    
     code: 200, data: "请求成功了" });
});


// 错误处理中间件,四个参数的函数,会被express认为是错误处理中间件
// 调用的位置,一般是在所有接口的后面,这样就能够拦截前面所有路径抛出的异常
// error与后面三个参数不同,是任意的,与之前next(errprParams) 有关
APP.use(function (error, req, res, next) {
    
    
  console.log("出错了", error.message);
  res.status("500");
  res.json({
    
    
    message: error.message,
  });
});

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

Considerations for Configuring Error Handling Middleware

  1. A function with four parameters (one cannot be less), will be considered as an error handling middleware by express
  2. The location of the call is generally behind all interfaces, so that exceptions thrown by all previous paths can be intercepted
  3. error is different from the last three parameters, it is customized and related to the previous next(errprParams)

call error handling middleware

  1. 'route'Only need to pass non -parameters in next
  2. next(params), where params is the first parameter error of the error handling middleware
  3. next()、next('route')、next(非route)next has these three calling methods, but the functions are different. next()It is to go to the next middleware, next('route')which is to skip multiple subsequent middleware called by the same app.use (app.get, etc.) next, which next(非route)is to call the middle of the error pieces

Middleware handles 404

The status code 404 is quite special, it means that the route requested by the client does not match in the server, therefore, in express projects, we generally need to use middleware to handle 404 at the end of all route configurations.

The middleware processing 404 and the error handling middleware do not affect each other.

var express = require("express");
var APP = express();
var PORT = 3000;

var router = require("./router");

// 挂载路由
APP.use(router);

// 404中间件处理,由于之前的所有router都没匹配到,前面的中间件都没有回复响应,我们需要这个中间件做兜底处理。
APP.use((req, res) => {
    
    
  res.status('404').send("404 not found")
});

// 错误处理中间件,四个参数的函数,会被express认为是错误处理中间件
// 调用的位置,一般是在所有接口的后面,这样就能够拦截前面所有路径抛出的异常
// error与后面三个参数不同,是任意的,与之前next(errprParams) 有关
APP.use(function (error, req, res, next) {
    
    
  console.log("出错了", error.message);
  res.status("500");
  res.json({
    
    
    message: error.message,
  });
});

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

built-in middleware

After express 4.x, the built-in middleware has been reduced to five, which are

  1. express.json parses the request body whose Content-Type is application/json format
  2. express.raw parses the request body whose Content-Type is octet-stream format
  3. express.text parses the request body whose Content-Type is text/plain format
  4. express.urlencoded parses the request body whose Content-Type is x-www-form-urlencoded format
  5. express.static hosts static resource files

The more commonly used ones are actually json urlencoded static
express.json When the client sends you json data, you need to use this middleware in express to get the data in req.body
express.urlencoded When the client sends you json data in the form This middleware needs to be used when sending requests in the form.
express.static When the client sends a file to the server, it needs to use

express official introduction built-in middleware address

The way of use, generally use the two commonly used built-in middleware at the top

var express = require("express");
var APP = express();
var PORT = 3000;

var router = require("./router");

//设置允许跨域访问该服务.
APP.all("*", function (req, res, next) {
    
    
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Content-Type");
  res.header("Access-Control-Allow-Methods", "*");
  res.header("Content-Type", "application/json;charset=utf-8");
  next();
});

// 调用内置中间件
var middlewares = [
  express.json(),
  express.urlencoded()
];
APP.use(middlewares);

// 挂载路由
APP.use(router);

// 404中间件处理,由于之前的所有router都没匹配到,前面的中间件都没有回复响应,我们需要这个中间件做兜底处理。
APP.use((req, res) => {
    
    
  res.status('404').send("404 not found")
});

// 错误处理中间件,四个参数的函数,会被express认为是错误处理中间件
// 调用的位置,一般是在所有接口的后面,这样就能够拦截前面所有路径抛出的异常
// error与后面三个参数不同,是任意的,与之前next(errprParams) 有关
APP.use(function (error, req, res, next) {
    
    
  console.log("出错了", error.message);
  res.status("500");
  res.json({
    
    
    message: error.message,
  });
});

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

third party middleware

Express officially maintains some third-party middleware and some recommended third-party middleware
https://expressjs.com/en/resources/middleware.html

Take one of the third-party middleware morgan as an example, a middleware that prints the response log.

Install

npm install morgan

use

var express = require("express");
var morgan = require("morgan");
var APP = express();
var PORT = 3000;

var router = require("./router");

//设置允许跨域访问该服务.
APP.all("*", function (req, res, next) {
    
    
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Content-Type");
  res.header("Access-Control-Allow-Methods", "*");
  res.header("Content-Type", "application/json;charset=utf-8");
  next();
});

var middlewares = [express.json(), express.urlencoded()];

APP.use(middlewares, morgan(':method :url :status :res[content-length] - :response-time ms'));

// 挂载路由
APP.use(router);

// 404中间件处理,由于之前的所有router都没匹配到,前面的中间件都没有回复响应,我们需要这个中间件做兜底处理。
APP.use((req, res) => {
    
    
  res.status("404").send("404 not found");
});

// 错误处理中间件,四个参数的函数,会被express认为是错误处理中间件
// 调用的位置,一般是在所有接口的后面,这样就能够拦截前面所有路径抛出的异常
// error与后面三个参数不同,是任意的,与之前next(errprParams) 有关
APP.use(function (error, req, res, next) {
    
    
  console.log("出错了", error.message);
  res.status("500");
  res.json({
    
    
    message: error.message,
  });
});

APP.listen(PORT, function () {
    
    
  console.log(`server runing at ${
      
      PORT}`);
});

Other content related to nodejs

nodejs commonjs introduces
nodejs fs module introduces
nodejs path module introduces
nodejs events module introduces
nodejs http module introduces nodejs
net module introduces
nodejs url module introduces
nodejs process module introduces
nodejs buffer module introduces
nodejs stream module introduces
nodejs express (1) module introduces

おすすめ

転載: blog.csdn.net/glorydx/article/details/129814496