[Node.js] Record express routing and middleware and the use of qs middleware in detail

The concept of routing

what is routing
  • Broadly speaking, routing is the mapping relationship
  • Mapping relationship between similar buttons and different services caused by buttons
Routing in Express
  • Routing in express refers to the mapping relationship between client requests and server functions
  • It consists of three parts
  • type of request
  • Requested URL address
  • processing function
// 导入express
const express = require('express')
// 创建web服务器
const app = express()
// 启动文本服务器
app.listen(80, () => {
    
    
    console.log("80服务器启动http://127.0.0.1/")
    console.log("80服务器2启动http://127.0.0.1/")
})
//app.请求类型(请求地址,代表服务器的处理函数)
app.get('/',function(req,res){
    
    
    res.send("hello 路由")
})

insert image description here

Route Matching Process
  • Whenever a request arrives at the server, it needs to be matched by the route first. Only when the match is successful, will the processing function be called
  • When matching, it will be matched according to the order of the route. If the request type and the requested URL are matched successfully at the same time, express will hand over the request to the corresponding function function for processing

use of routing

  • The easiest way is to mount the route to the app, which has a lot of code and is not commonly used
//app.请求类型(请求地址,代表服务器的处理函数)
app.get('/',function(req,res){
    
    
    res.send("hello 路由")
})
app.post('/',function(req,res){
    
    
    res.send("hello 路由post")
})
Create routing module file
  • Modular routing, which separates the routing into separate modules
    – Step 1: Create the js file corresponding to the routing module
    – Step 2: Call the express.Router() function to create the routing object
    – Step 3: Mount the specific routing to the routing object
    – Step 4: Use module.exports to share routing objects outward
// 导入express
const express = require('express')
// 创建web服务器
const app = express()
// 创建路由对象
const router = express.Router()
router.get('/', function (req, res) {
    
    
    res.send("hello 路由")
})
router.post('/', function (req, res) {
    
    
    res.send("hello 路由post")
})
//向外共享路由对象
module.exports = router
Register routing module file
// 导入express
const express = require('express')
// 创建web服务器
const app = express()
// 导入路由
const userRouter = require('./router')
// 启动文本服务器
app.listen(80, () => {
    
    
    console.log("80服务器启动http://127.0.0.1/")
})
//使用app.use()注册路由模块,app.user()函数的作用,就是来注册全局中间件的
app.use(userRouter)

insert image description here

Add a prefix to the routing module
//添加统一的访问前缀/api,此时想访问userRouter里的路由就得添加/api
app.use('/api',userRouter)

insert image description here

Express middleware

  • Intermediate treatment process similar to sewage treatment
  • The calling process of express middleware
  • When a request arrives at the Express server, multiple middleware can be called continuously to preprocess the request
    insert image description here
Express middleware format
  • The essence is a function processing function
  • The formal parameter list of the middleware function must contain the next parameter and be placed at the end, while the route processing function only contains req and res
  • What does the next function do?
  • The next function is the key to realize the continuous invocation of multiple middleware, and it means to transfer the flow relationship to the next middleware or route
  • That is, the middleware 1 in the above figure executes and calls the next function, to the middle 2, etc.
Define middleware functions
  • After the business processing of the middleware is completed, the next() function must be called to indicate that the transfer relationship is handed over to the next middleware or route
//定义中间件函数
const nw = function (req, res, next) {
    
    
    console.log("中间件函数")
    next()
}
Define a middleware function that takes effect globally
  • All requests initiated by the client will trigger middleware after reaching the server, which is called globally effective middleware
  • By calling app.use(middleware function), you can define a globally effective middleware
//定义中间件函数
const nw = function (req, res, next) {
    
    
    console.log("中间件函数")
    next()
}
//将nw注册为全局生效的中间件
app.use(nw)
//或者,组合使用注册
app.use(function (req, res, next) {
    
    
    console.log("中间件函数")
    next()
})
//或者,es语法组合使用
app.use((req, res, next)=> {
    
    
    console.log("中间件函数")
    next()
})

app.get('/1',function(req,res){
    
    
    res.send("hello 路由")
})

- Execute, the middleware function will be printed on the console, the next component is next, and the hello route will arrive without the next component
insert image description here

The role of middleware
  • Multiple middleware share the same req and res. Based on this feature, we can uniformly add custom properties or methods to the req or res object in the upstream middleware for use by downstream middleware or routing
//定义中间件函数
app.use((req, res, next) => {
    
    
    const time = Date.now()
    req.time = time
    console.log("中间件函数")
    next()
})
//下游的中间件或者路由也能用
app.get('/', function (req, res, next) {
    
    
    res.send("hello 路由get"+ req.time)
})
Define multiple global middleware
  • Multiple global middleware can be defined consecutively using app.use()
  • After the client request reaches the server, it will be called in sequence according to the order defined by the middleware
//定义中间件函数
app.use((req, res, next) => {
    
    
    const time = Date.now()
    req.time = time
    console.log("中间件函数")
    next()
})
//定义中间件函数
app.use((req, res, next) => {
    
    
    const time = Date.now()
    req.time = time
    console.log("中间件函数2")
    next()
})
//定义中间件函数
app.use((req, res, next) => {
    
    
    const time = Date.now()
    req.time = time
    console.log("中间件函数3")
    next()
})
locally valid middleware
  • Do not use the middleware defined by app.use, the middleware will be executed only when the specified route is taken, first take the middleware, and then take the route
//定义中间件函数
const nw = function (req, res, next) {
    
    
    console.log("中间件函数")
    next()
}
//第二个参数就是中间件名称
app.get('/666',nw,function (req, res) {
    
    
    res.send("hello 路由get")
})
Define multiple locally valid middleware
const nw = function (req, res, next) {
    
    
    console.log("中间件函数")
    next()
}
const nw1 = function (req, res, next) {
    
    
    console.log("中间件函数2")
    next()
}
//下面两种方式完全等价,用哪种方式都行
//第二个参数就是中间件名称
app.get('/666',nw,nw1,function (req, res) {
    
    
    res.send("hello 路由get")
})
//第二个参数就是中间件名称
app.get('/666',[nw,nw1],function (req, res) {
    
    
    res.send("hello 路由get")
})
Understand the precautions for using middleware
  • Be sure to register the middleware before routing, otherwise it will not take effect
  • The request sent by the client can call multiple middleware continuously for processing
  • After executing the business code of the middleware, don't forget to call the next() function
  • In order to prevent code logic confusion, do not write additional code after calling the next() function
  • When multiple middlewares are called continuously, the req and res objects are shared between multiple middlewares

Classification of middleware

  • Application level middleware
  • Route-level middleware
  • error level middleware
  • Express built-in middleware
  • third-party middleware
Application level middleware
  • Middleware bound to the app instance via app.use or app.get() or app.post()
//全局中间件
app.use((req, res, next) => {
    
    
    const time = Date.now()
    req.time = time
    console.log("中间件函数")
    next()
})
//局部中间件
app.get('/666',nw,function (req, res) {
    
    
    res.send("hello 路由get")
})
Route-level middleware
  • Middleware bound to express.Router() instance
const express = require('express')
// 创建web服务器
const app = express()
// 导入路由
const router= require('./router')
router.use((req, res, next) => {
    
    
    const time = Date.now()
    req.time = time
    console.log("中间件函数")
    next()
})
// 启动文本服务器
app.listen(80, () => {
    
    
    console.log("80服务器启动http://127.0.0.1/")
})
//使用app.use()注册路由模块,app.user()函数的作用,就是来注册全局中间件的
app.use(router)
error level middleware
  • The role of error-level middleware: it is specially used to capture abnormal errors that occur in the entire project, thereby preventing the project from crashing abnormally
  • Format:
  • In the processing function of the middleware of the error level, there must be four parameters, namely (err, req, res, next)
  • Error level middleware must be registered after all routes
// 导入express
const express = require('express')
// 创建web服务器
const app = express()
// 启动文本服务器
app.listen(80, () => {
    
    
    console.log("80服务器启动http://127.0.0.1/")
})

//路由
app.get('/666',function (req, res) {
    
    
    throw new Error("抛出定义错误")
    res.send("hello get")
})
//会崩溃,所以接下来演示全局的中间件
//定义错误中间件函数
const nw = function (err,req, res, next) {
    
    
    res.send("检测定义错误1"+err.message)
    next()
}
app.use(nw)
expressd's built-in middleware
  • Since version 4.16.0, Express has built-in 3 commonly used middleware, improving development efficiency and experience
  • 1. express.static is a built-in middleware for quickly hosting static resources
  • 2. express.json parses the request body data in json format
  • 3. express.urlencoded parses request body data in URL-encoded format (similarly)
//路由
app.get('/',function (req, res) {
    
    
    // 在服务器可以使用req.body这个属性,来接受客户端发送过来的数据
    console.log(req.body)
    res.send("hello get")
})
  • The req.body attribute can be used on the server to accept the data sent by the client
  • By default, if no middleware for parsing form data is configured, req.body is equal to undefined by default
    insert image description here
  • Solution: configure express.json middleware
  • If it is still an empty object, check whether the request header automatically generated by postman is ticked (not reproduced)
app.use(express.json)
app.use(express.urlencoded({
    
    extended:false}))
app.get('/',function (req, res) {
    
    
    // 在服务器可以使用req.body这个属性,来接受客户端发送过来的数据
    console.log(req.body)
    res.send("hello get")
})
third-party middleware
  • Middleware developed by a third party, you can download and configure third-party middleware on demand
  • Run npm install body-parser to install middleware
  • Run require to import middleware
  • Call app.use() to register middleware
  • Note: Express's built-in express.urlencoded() middleware is further encapsulated based on the third-party middleware body-parser
//导入组件
const parser =require('body-parser')
//使用app.use()注册中间件
app.use(parser.urlencoded({
    
    extended:false}))
//路由
app.get('/',function (req, res) {
    
    
    // 在服务器可以使用req.body这个属性,来接受客户端发送过来的数据
    console.log(req.)
    res.send(req.query)
})

Custom middleware case

Manually simulate a middleware like express.urlerlencoded to parse the form data submitted by POST to the server

  • Define middleware
  • Listen to the data event of req
  • Listen to the end event of req

If the amount of data is too large to be sent all at once, the client will cut the data and send it to the server in batches, so the data event may be triggered multiple times. For each trigger, the obtained data is only a part of the complete data, which needs to be spliced ​​manually

  • Use querystring to simulate parsing request body data

Node.js has a built-in querystring module, which is specially used to process query strings. The parse() function provided by this module parses the queried string into an object format

  • Mount the parsed data as req.body

Because the upstream middleware and downstream middleware and routing share the same req and res, we can mount the parsed data as a custom attribute of req and name it req.body for downstream use

// 导入express
const express = require('express')
// 创建web服务器
const app = express()
// 启动文本服务器
app.listen(80, () => {
    
    
    console.log("80服务器启动http://127.0.0.1/")
})
//导入内置querystring模块
const qs = require('querystring')
//中间件的业务逻辑
app.use((req, res, next) => {
    
    
    let str = ""
    //监听req对象的data事件。客户端发送过来的新的请求体数据
    req.on('data', (chunk) => {
    
    
        //拼接请求体数据,格式转为字符串
        str += chunk
    })
    //当请求体数据接收完毕之后,会自动触发req的end事件
    req.on('end', () => {
    
    
        //可以拿到完整的请求体数据
        console.log(str)
        //字符串格式解析为对象格式
        const body = qs.parse(str) 
        //挂载为自定义属性req.body
        req.body=body
        next()
    })
})
//路由
app.post('/', function (req, res) {
    
    
    //下游使用挂载的req.body
    res.send(req.body)
})

insert image description here

  • Encapsulate custom components as components
  • Package file parse.js
//导入内置querystring模块
const qs = require('querystring')
//中间件的业务逻辑
const bodyParse=(req, res, next) => {
    
    
    let str = ""
    //监听req对象的data事件。客户端发送过来的新的请求体数据
    req.on('data', (chunk) => {
    
    
        //拼接请求体数据,格式转为字符串
        str += chunk
    })
    //当请求体数据接收完毕之后,会自动触发req的end事件
    req.on('end', () => {
    
    
        //可以拿到完整的请求体数据
        console.log(str)
        //字符串格式解析为对象格式
        const body = qs.parse(str) 
        //挂载为自定义属性req.body
        req.body=body
        next()
    })
}
module.exports=bodyParse
  • call module
// 导入express
const express = require('express')
// 创建web服务器
const app = express()
// 启动文本服务器
app.listen(80, () => {
    
    
    console.log("80服务器启动http://127.0.0.1/")
})
//导入自己封装的组件
const bodyParse=require('./parse')
app.use(bodyParse)
//路由
app.post('/', function (req, res) {
    
    
    //下游使用挂载的req.body
    res.send(req.body)
})

Guess you like

Origin blog.csdn.net/weixin_44899940/article/details/129164812