第三方Express 路由和路由中间件

server/2024/12/2 9:19:08/

文章目录

  • 1、Express 应用使用回调函数的参数: request 和 response 对象来处理请求和响应的数据。
  • 2、Express路由
    • 1.路由方法
    • 2.路由路径
    • 3.路由处理程序
  • 3. 模块化路由
  • 4. Express中间件


1、Express 应用使用回调函数的参数: request 和 response 对象来处理请求和响应的数据。

  1. Request 对象
    request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性
    属性/方法说明
    app当callback为外部文件时,用req.app访问express的实例
    baseUrl获取路由当前安装的URL路径
    body/cookies获得「请求主体」/ Cookies
    fresh/stale判断请求是否还「新鲜」
    hostname/ip获取主机名和IP地址
    originalUrl获取原始请求URL
    params获取路由的parameters
    path获取请求路径
    protocol获取协议类型
    query获取URL的查询参数串
    route获取当前匹配的路由
    subdomains获取子域名
    accepts()检查可接受的请求的文档类型
    acceptsCharsets/acceptsEncodings/acceptsLanguages返回指定字符集的第一个可接受字符编码
    get()获取指定的HTTP请求头
    is()判断请求头Content-Type的MIME类型
  2. Response 对象
    response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据
    属性/方法说明
    app当callback为外部文件时,用req.app访问express的实例
    append()追加指定HTTP头
    set()在res.append()后将重置之前设置的头
    res.cookie(name,value [,option])设置Cookie
    opitiondomain / expires / httpOnly / maxAge / path / secure / signed
    clearCookie()清除Cookie
    download()传送指定路径的文件
    get()返回指定的HTTP头
    json()传送JSON响应
    jsonp()传送JSONP响应
    location()只设置响应的Location HTTP头,不设置状态码或者close response
    redirect()设置响应的Location HTTP头,并且设置状态码302
    render(view,[locals],callback)渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
    send()传送HTTP响应
    sendFile(path [,options] [,fn])传送指定路径的文件 -会自动根据文件extension设定Content-Type
    set()设置HTTP头,传入object可以一次设置多个头
    status()设置HTTP状态码
    type()设置Content-Type的MIME类型

2、Express路由

路由是指应用程序的终端节点 (URI) 如何响应客户端请求。
在Express中,路由指的是客户端的请求与服务器处理函数之间的映射关系。
Express中的路由分3部分组成,分别是请求的类型、请求的URL地址、处理函数,格式如下:app.method(path, handler)

1.路由方法

// GET method route
app.get('/', function (req, res) {res.send('GET request')
})// POST method route
app.post('/', function (req, res) {res.send('POST request')
})

app.all() 用于在所有 HTTP 请求方法的路径上加载中间件函数。
无论是使用 GET、POST、PUT、DELETE 还是 http 模块中支持的任何其他 HTTP 请求方法,都会对路由 “/secret” 的请求执行以下处理程序。

app.all('/secret', function (req, res, next) {console.log('all')next() // pass control to the next handler
})

2.路由路径

路由路径可以是字符串、字符串模式或正则表达式。

// acd和abcd
app.get('/ab?cd', function (req, res) {res.send('ab?cd')
})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:问号前面字符可有可无

app.get('/ab(cd)?e', function (req, res) {res.send('ab(cd)?e')
})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:问号前面括号内的字符可有可无

app.get('/ab+cd', function (req, res) {res.send('ab+cd')
})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:加号前面字符可无限叠加

app.get('/ab*cd', function (req, res) {res.send('ab*cd')
})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:星号前面的字符为开始,后边的字符为结束字符,中间可以任意字符或数字

app.get(/a/, function (req, res) {res.send('/a/')
})

在这里插入图片描述
在这里插入图片描述
总结:满足正则/a/的都满足此方法

app.get(/.*fly$/, function (req, res) {res.send('/.*fly$/')
})

在这里插入图片描述
在这里插入图片描述

总结:满足正则/.*fly$/以fly字符结束的路由

3.路由处理程序

在没有理由继续当前路由时将控制权传递给后续路由。next(‘route’)
路由处理程序可以采用函数、函数数组或两者的组合形式。

  1. 单个回调函数可以处理路由。

    var express = require('express');
    var app = express();
    app.get('/abc', function (req, res) {res.send('hello abc');
    })
    app.listen(8081, function () {console.log("服务启动")
    })
    
  2. 多个回调函数可以处理一个路由(确保指定对象)next();

    var express = require('express');
    var app = express();
    app.get('/abc', function (req, res, next) {console.log(111)next()
    }, function(req, res) {res.send('hello abc next');
    })
    app.listen(8081, function () {console.log("服务启动")
    })	
    

    在这里插入图片描述
    在这里插入图片描述

  3. 回调函数数组可以处理路由。

    var express = require('express');
    var app = express();
    var a0 = function (req, res, next) {console.log('A0')next()
    }
    var a1 = function (req, res, next) {console.log('A1')next()
    }
    var a2 = function (req, res) {res.send('Hello from A!')
    }
    app.get('/abc', [a0, a1, a2])
    app.listen(8081, function () {console.log("服务启动")
    })
    

    在这里插入图片描述
    在这里插入图片描述

  4. 独立函数和函数数组的组合可以处理路由。

    var express = require('express');
    var app = express();
    var a1 = function (req, res, next) {console.log('A1')next()
    }
    var a2 = function (req, res) {res.send('Hello from A!')
    }
    app.get('/abc', function (req, res, next) {console.log('A0')next()
    },[a1, a2])
    app.listen(8081, function () {console.log("服务启动")
    })
    

    在这里插入图片描述
    在这里插入图片描述

3. 模块化路由

为了方便对路由进行模块化的管理,Express不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块。

将路由抽离为单独模块的步骤如下:
1.创建路由模块对应的.js文件
2.调用express.Router()函数创建路由对象
3.向路由对象上挂载具体的路由
4.使用module.exports向外共享路由对象
5.使用app.use()函数注册路由模块

  1. 创建路由模块
    // router.js   文件
    var express = require('express'); // 1.导入express
    var router = express.Router();    // 2.创建路由对象router.get('/login/info', (req, res) => {   // 3.挂载登录用户信息res.send('Get user list.');
    });
    router.post('/singUp/add', (req, res) => {   // 4.挂载注册用户的路由res.send('Add new user.');
    });
    module.exports = router;  // 5.向外导出路由对象
    
  2. 注册路由模块
    const express = require('express');
    const app = express();
    // 1.导入路由模块
    const userRouter = require('./router.js');
    // 2.使用app.use()注册路由模块
    app.use(userRouter);
    app.listen(8081, () => {console.log('http://127.0.0.1')
    })
    
  3. 为路由模块添加前缀
    // 类似于托管静态资源时,为静态资源统一挂载访问前缀一样
    // 1.导入路由模块
    const userRouter = require('./router.js');
    // 2.使用app.use()注册路由模块,并添加统一的范围前缀 /api 
    app.use('/api', userRouter);
    

4. Express中间件

1.中间件简介

  1. 中间件简介
    中间件是一种特殊的路由处理函数,它可以在请求到达目标处理函数之前,进行一些预处理操作。Express 支持使用中间件来实现各种功能,例如身份验证、请求日志记录,处理 CORS(跨源资源共享)等。
    注意:中间件函数的形参列表中,必须包含next参数,而路由处理函数中只包含req和res。
    next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。
    可以使用app.use()连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用
    const express = require('express');
    const app = express();
    // 一个简单的中间件
    app.use((req, res, next) => {console.log(`Request received at ${new Date()}`);next(); // 将控制权传递给下一个中间件或路由处理器
    });
    // 一个路由处理器,用于处理 GET 请求
    app.get('/', (req, res) => {res.send('Hello, World!');
    });// 启动服务器
    app.listen(8081, () => {console.log('Server is running on port 8081');
    });
    
    在这里插入图片描述
  2. 局部中间件
    不使用app.use()定义的中间件,叫做局部生效的中间件中间件只在"当前路由中生效",
    var express = require('express');
    var app = express();var myLogger = function (req, res, next) {console.log('LOGGED')next()
    }
    app.get('/', myLogger, function (req, res) {res.send('Hello World!')
    })
    
    在这里插入图片描述
  3. 中间件的5个使用注意事项
    • 一定要在路由之前注册中间件
    • 客户端发送过来的请求,可以连续调用多个中间件进行处理
    • 执行完中间件的业务代码之后,不要忘记调用next()函数
    • 为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
    • 连续调用多个中间件时,多个中间件之间,共享req和res对象
  4. 监听 req 的 data 事件
    中间件中,需要监听req对象的data事件,来获取客户端发送到服务器的数据。
    如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以data事件可能会触发多次,每一次触发data事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接。
    // 定义变量,用来储存客户端发送过来的请求体数据
    let str = ''
    // 监听 req 对象的 data 事件(客户端发送过来的新的请求体数据)
    req.on('data',(data) => {// 打印请求数据console.log(data)
    })
    
  5. 监听 req 的 end 事件
    当请求体数据接收完毕之后,会自动触发req的end 事件。
    可以在req的end 事件中,拿到并处理完整的请求体数据。
    // 监听 req 对象的 end 事件(请求体发送完毕后自动触发)
    req.on('end',() => {// => 打印完整的请求体数据console.log(str)// TODO: 业务逻辑// .......
    })
    

2.中间件分类

  1. 应用程序级中间件
    通过app.use()或app.get()或 app.post(),绑定到app实例上的中间件,叫做应用级别的中间件
    var app = express();
    var myLogger = function (req, res, next) {console.log('LOGGED')next()
    }
    // 应用级别的中间件(全局中间件)
    app.use((req, res, next) => {req.name = 'router'req.on('end',() => {console.log('end')})next();
    });
    // 应用级别的中间件(局部中间件)
    app.get('/', myLogger, (req, res) => {console.log(req.name)res.send('Home page.')
    });
    app.listen(8081, function () {console.log("服务启动")
    })
    
    在这里插入图片描述
  2. 路由器级中间件
    绑定到express.Router()实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到 app实例上,路由级别中绚件摸定到router 实例上
    var express = require('express')
    var app = express()
    var router = express.Router()
    router.use(function (req, res, next) {console.log('Time:', Date.now());next()
    })
    app.use('/', router)
    app.listen(8081, function () {console.log("服务启动")
    })
    
    在这里插入图片描述
  3. 错误处理中间件
    错误处理中间件是专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。
    格式:错误级别的中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是(err,req,res,next)。
    注意:错误级别的中间件,必须注册在所有路由之后
    app.get('/', (req, res) => { // 1.路由throw new Error('服务器内部发生了错误');  // 1.1.抛出一个自定义的错误res.send('Home Page.');
    });
    app.use((err, req, res, next) => {    // 2.错误级别的中间件console.log('发生了错误:' + err.message);   // 2.1.在服务器打印错误消息res.send('Erroe!' + err.message); // 2.2.向客户端响应错误相关的内容
    });
    
  4. 内置中间件
    三个内置的中间件分别是
    express.static 是快速托管静态资源的内置中间件 例如:HTML文件、图片、CSS样式等(无兼容性)
    express.json是拿来解析json格式数据的
    express.urlencoded是拿来解析urlencoded格式数据的
    var express = require('express');
    var app = express();
    // 注意这是中间件 所以必须配置到路由之前
    app.use(express.json())
    app.use(express.urlencoded({extended : false}))
    app.listen(8081, function () {console.log("服务启动")
    })
    
  5. 第三方中间件
    非Express官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率。
    安装所需功能的 Node.js 模块,然后在应用程序级别或路由器级别将其加载到应用程序中。
    以cookie-parser为示例:
    $ npm install cookie-parser
    
    var express = require('express')
    var app = express()
    var cookieParser = require('cookie-parser')
    app.use(cookieParser())
    

3.自定义中间件

自定义中间件步骤:

  1. 定义中间件
  2. 监听req的data事件
  3. 监听req的end事件
  4. 使用querystring模块解析请求体数据
  5. 将解析出来的数据对象挂载为req.body
  6. 将自定义中间件封装为模块
    // myparse.js
    //1.1 导入内置模块
    const qs=require('querystring')
    //1.2 编写解析函数
    function myparse(req,res,next){//2.2 定义一个变量存储客户端字符串let str=''//2.1 对客户端请求数据的监听//注意是对客户端对象进行监听,而不是服务器req.on('data',(chunk)=>{str+=chunk})//2.4 进行发送数据结束的监听req.on('end',()=>{//倘若有响应,说明数据发送结束,我们已经拿到所有数据console.log(str)//4.2 利用内置模块的parser()进行数据解析const body=qs.parse(str)//4.3 进行数据对象的挂载req.body=bodyconsole.log(body)})//2.5 不要忘记需要调用next函数next()
    }
    //1.4 通过module.exports暴露
    module.exports = myparse
    
    // 使用
    var express = require('express');
    var app = express();
    // 2.1 导入自定义解析模块
    const myparse = require('./mybody-parse')
    app.use(myparse)
    app.get('/login', function (req, res) {console.log(req.body);res.end(req.body);
    })
    

http://www.ppmy.cn/server/146667.html

相关文章

探索温度计的数字化设计:一个可视化温度数据的Web图表案例

随着科技的发展,数据可视化在各个领域中的应用越来越广泛。在温度监控和展示方面,传统的温度计已逐渐被数字化温度计所取代。本文将介绍一个使用Echarts库创建的温度计Web图表,该图表通过动态数据可视化展示了温度值,并通过渐变色…

Electron + vue3 打包之后不能跳转路由

路由不跳转问题原因: 是因为electron需要将vue-router的mode调整为hash模式(两种写法) export default new Router({mode: hash, //这里history修改为hashscrollBehavior: () > ({y: 0}),routes: constantRouterMap, }) export default new createRouter({his…

npm install -g@vue/cli报错解决:npm error code ENOENT npm error syscall open

这里写目录标题 报错信息1解决方案 报错信息2解决方案 报错信息1 使用npm install -gvue/cli时,发生报错,报错图片如下: 根据报错信息可以知道,缺少package.json文件。 解决方案 缺什么补什么,这里我们使用命令npm…

vscode python code runner执行乱码

打开vscode code runner插件配置,如图所示: 然后在setting.json修改运行python的默认命令: 将原来 替换成 "python":"set PYTHONIOENCODINGutf8 && python", 参考:Vscode——python环境输出中文乱…

【IMF靶场渗透】

文章目录 一、基础信息 二、信息收集 三、flag1 四、flag2 五、flag3 六、flag4 七、flag5 八、flag6 一、基础信息 Kali IP:192.168.20.146 靶机IP:192.168.20.147 二、信息收集 Nmap -sP 192.168.20.0/24 Arp-scan -l nmap -sS -sV -p- -…

三数求大 C语言

题目描述 从键盘获取三个整数,从大到小输出这3个数字. 代码实现 两个数交换,需要用到第三个变量tmp:

error MSB8041:此项目需要MFC库。从visual studio安装程序(单个组件选项卡)为正在使用的任何工具和体系结构安装他们

系列文章目录 文章目录 系列文章目录前言一、问题原因二、解决步骤1.打开Visual Studio Installer2.修改3.使用c的桌面开发,先把勾选去掉,然后再重新勾选,这样右侧会自动匹配对应的MFC版本5.visual studio installer更新到最新版本3.单个组件…

docker 在ubuntu系统安装,以及常用命令,配置阿里云镜像仓库,搭建本地仓库等

1.docker安装 1.1 先检查ubuntu系统有没有安装过docker 使用 docker -v 命令 如果有请先卸载旧版本,如果没有直接安装命令如下: 1.1.0 首先,确保你的系统包是最新的: 如果是root 权限下面命令的sudo可以去掉 sudo apt-get upda…