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

文章目录

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


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=body
            console.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);
    })
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/926397.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx+php压测及报错优化

测试环境:虚拟机centos7,nginxphp 压测工具:Apipost 访问的php程序中添加sleep()增加程序执行时长,使用Apipost进行压测,根据服务器配置设置一个大概可能触发报错的并发和轮训次数,若无报错逐渐增加并发和…

探索Python词云库WordCloud的奥秘

文章目录 探索Python词云库WordCloud的奥秘1. 背景介绍:为何选择WordCloud?2. WordCloud库简介3. 安装WordCloud库4. 简单函数使用方法5. 应用场景示例6. 常见Bug及解决方案7. 总结 探索Python词云库WordCloud的奥秘 1. 背景介绍:为何选择Wo…

AOSP的同步问题

repo sync同步时提示出错: error: .repo/manifests/: contains uncommitted changesRepo command failed due to the following UpdateManifestError errors: contains uncommitted changes解决方法: 1、cd 进入.repo/manifests cd .repo/manifests2、执行如下三…

Shell脚本小练习

学习了这么长时间Shell脚本,总得来一次小小的练习吧,那么请看下文! 1.用Shell写一个小计算器。 通过read命令获取用户输入的表达式,表达式的格式设定为操作数1 运算符 操作数2,例如53,然后利用设计的脚本…

k8s Init:ImagePullBackOff 的解决方法

kubectl describe po (pod名字) -n kube-system 可查看pod所在的节点信息 例如&#xff1a; kubectl describe po calico-node-2lcxx -n kube-system 执行拉取前先把用到的节点的源换了 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"re…

Git 快速入门:全面了解与安装步骤

Git 快速入门&#xff1a;全面了解与安装步骤 一、关于Git 1.1 简介 Git 是一个开源的分布式版本控制系统&#xff0c;由 Linus Torvalds 于 2005 年创建&#xff0c;最初是为了更好地管理 Linux 内核开发而设计。 Git用于跟踪计算机文件的变化&#xff0c;特别是源代码文件…

springboot358智慧社区居家养老健康管理系统(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 智慧社区居家养老健康管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&…

探索 IntelliJ IDEA 中 Spring Boot 运行配置

前言 IntelliJ IDEA 作为一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;为 Spring Boot 应用提供了丰富的运行配置选项&#xff0c;定义了如何在 IntelliJ IDEA 中运行 Spring Boot 应用程序&#xff0c;当从主类文件运行应用程序时&#xff0c;IDE 将创建…

快速讲图片中的公式粘贴到word中

只是个人学习记录&#xff0c;不具备教学意义 目的&#xff1a; 比如下面图片中的公式 我们想把这个公式整到我们的word上&#xff0c;传统的方法是通过安装MathType插件&#xff0c;然后慢慢打。我说这样你就慢了。 解决办法&#xff1a; 前提准备&#xff1a; 我们需要…

【STM32+HAL】FreeRTOS学习小札

一、RTOS程序任务结构 如上图所示&#xff0c;在实时操作系统中&#xff0c;开发人员可以把要实现的功能划分为多个任务&#xff0c;每个任务负责实现其中的一部分&#xff0c;每个任务都是一个很简单的程序&#xff0c;通常是一个死循环。 二、多任务系统基本概念 1、FreeRTO…

复杂网络(四)

一、规则网络 孤立节点网络全局耦合网络&#xff08;又称完全网络&#xff09;星型网络一维环二维晶格 编程实践&#xff1a; import networkx as nx import matplotlib.pyplot as pltn 10 #创建孤立节点图 G1 nx.Graph() G1.add_nodes_from(list(range(n))) plt.figure(f…

安规题库;安全测试题;安规刷题;大风车excel

一、电网安规题库、试题 安规真的是年年考&#xff0c;天天背&#xff0c;时不时抽考 往往需要利用上下班的零碎时间来练习和记忆 分享一套电网真题、原题&#xff08;150道选择题&#xff09; 上面的试题&#xff0c;我已经导入到刷题工具&#xff08;大风车excel&#xff…

ElasticSearch学习篇19_《检索技术核心20讲》搜推广系统设计思想

目录 主要是包含搜推广系统的基本模块简单介绍&#xff0c;另有一些流程、设计思想的分析。 搜索引擎 基本模块检索流程 查询分析查询纠错 广告引擎 基于标签倒排索引召回基于向量ANN检索召回打分机制&#xff1a;非精确打分精准深度学习模型打分索引精简&#xff1a;必要的…

BWO-CNN-BiGRU-Attention白鲸优化算法优化卷积神经网络结合双向门控循环单元时间序列预测,含优化前后对比

BWO-CNN-BiGRU-Attention白鲸优化算法优化卷积神经网络结合双向门控循环单元时间序列预测&#xff0c;含优化前后对比 目录 BWO-CNN-BiGRU-Attention白鲸优化算法优化卷积神经网络结合双向门控循环单元时间序列预测&#xff0c;含优化前后对比预测效果基本介绍模型描述程序设计…

Matlab Simulink HDL Coder FPGA开发初体验—计数器

目录 一、Simulink设计及仿真二、Verilog HDL代码转换1、参数配置2、HDL代码生成 三、ModelSim仿真分析1、使用自己编写的Testbench文件进行仿真2、使用HDL Coder生成的Testbench文件进行仿真 前言 Simulink HDL Coder‌是一款将Simulink和Stateflow模型转化为可综合的Verilog和…

RAG数据拆分之PDF

引言RAG数据简介PDF解析方法及工具代码实现总结 二、正文内容 引言 本文将介绍如何将RAG数据拆分至PDF格式&#xff0c;并探讨PDF解析的方法和工具&#xff0c;最后提供代码示例。 RAG数据简介 RAG&#xff08;关系型属性图&#xff09;是一种用于表示实体及其关系的图数据…

Postman设置接口关联,实现参数化

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 postman设置接口关联 在实际的接口测试中&#xff0c;后一个接口经常需要用到前一个接口返回的结果&#xff0c; 从而让后一个接口能正常执行&#xff0c;这…

不玩PS抠图了,改玩Python抠图

网上找了两个苏轼的印章图片&#xff1a; 把这两个印章抠出来的话&#xff0c;对于不少PS高手来说是相当容易&#xff0c;但是要去掉其中的水印&#xff0c;可能要用仿制图章慢慢描绘&#xff0c;图章的边缘也要慢慢勾画或者用通道抠图之类来处理&#xff0c;而且印章的红色也不…

构造函数与析构函数错题汇总

构造函数不能定义返回类型&#xff0c;也没有返回类型。 堆、栈、静态存储区。栈上的对象main函数结束就释放&#xff0c;堆上的需要手动释放&#xff0c;静态存储区的在所在作用域的程序结束时释放。这里static在main函数内&#xff0c;是局部变量&#xff0c;所以作用域为…

模拟器快速上手,助力HarmonyOS应用/服务高效开发

文章目录 1 创建模拟器1&#xff09;打开设备管理界面2&#xff09;设置本地模拟器实例存储路径3&#xff09;创建一个模拟器&#xff08;1&#xff09;选择模拟器设备&#xff08;2&#xff09;创建模拟器&#xff08;3&#xff09;启动模拟器&#xff08;4&#xff09;关闭模…