【Express.js】处理请求数据

news2024/12/28 17:42:16

处理请求数据

本节将具体介绍express后端处理请求源携带数据的一些方法和技巧

动态路径

很多时候我们需要处理一些类似但有操作差别或不同对象的业务,我们可以监听一段基本路径,将其中某一个段或者某几段路径作为变量,在接口中根据不同的路径变量执行不同的业务操作,这是一种REST风格比较鲜明的动态接口设计策略

实践

由于post也可以url传参,本节所有实例均采用post请求

第一个接口

这个接口以 /request/data/ 作为基路由,之后的kind变化的,在接口内部根据kind的值进行分支化处理。我指定了kind的3个值:PathVarible, RequestParam 和 body.
所有的路径参数则可以由req.params(大概是个json对象)来获取,我要指定获取kind的值,就req.params.kind,而静态路径变量的值就等于它名字.

//忽略了express项目的创建和基本配置
class Item {
    constructor(name, value) {
      this.name = name;
      this.value = value;
    }
}
//启用json解析请求体
app.use(express.json({type: 'application/json'}));
app.post('/request/data/:kind', function (req, res) {
    let result = [];
    if (req.params.kind == 'PathVarible') {
        result.push(new Item("lesson","路径变量"));
        result.push(new Item("info","在express中叫做params,路径上每个被双单斜杠'/'隔开的一个个词语就是路径参数,当你需要在同一个接口内动态响应不同的情景时,可以让某一处或多出的路径参数前面加上一个冒号,长得比较像vue中的动态绑定,动态路径在REST风格上被广泛运行,比如操作某个用户: 'user/:id => 'user/1"))
    } else if (req.params.kind == 'RequestParam') {
        result.push(new Item("lesson","请求参数"));
        result.push(new Item("info","在express中叫做query,和路径变量相比,前者更像是前端主动携带参数去访问特定的资源,而后者更像是后端要求必须携带的数据,前端被迫携带,反应在路径上形式一般是: '/stu?class=2&sid=1&name='evanp',在基本路径之后添上一个问号,然后在后面加上请求的参数,不同参数之间用'&'符号隔开"))
    } else if (req.params.kind == 'body') {
        result.push(new Item("lesson","请求体"));
        result.push(new Item("info","路径变量和请求参数的数据都是透明的,这非常不注重隐私,因此更多时候前端应该将携带的数据放在请求体内进行传输。请求体的形式有很多,最常用的是表单和JSON,请在路径后新增一个路径变量,form-urlencode, multi-form-data或json导向不同的接口进行查看"));
    } else {
        result.push(new Item("error","这个参数不认识"));
    }
    res.send(result);
});

接口测试

请使用接口调试工具,带上路径查询参数(query),然后修改不同的kind为不同的值,去POST访问 localhost:8080/request/data/kind,看看它们的返回结果,注意kind前不要加冒号了,冒号是用来让express知道这段路径是可变的

第二个接口

当第一个接口的某一个分支还可以有后续的操作时,可以再开一个接口以它作为基路由,往后新增动态路径,比如我现在要让body可以再导向不同的分支,就再开一个 /request/data/body/:kind 接口

app.post('/request/data/body/:kind', function (req, res) {
    let result = [];
    if (req.params.kind == 'json') {
        result.push(new Item("lesson","json请求体"));
        result.push(new Item("body",req.body));
        result.push(new Item("info","express想解析json形式的body,必须先开启express.json: 'app.use(express.json)',之后就可以用req.body来接收请求体了"));
        result.push(new Item("trick","进阶技巧,读取请求体时可以用match模式匹配成自己想要的格式或命名,常用于实体注入及转化等"));
    } else if (req.params.kind == 'form-urlencode') {
        result.push(new Item("lesson","form-urlencode请求体"));
        result.push(new Item("body",req.body));
    } else if (req.params.kind == 'multi-form-data') {
        result.push(new Item("lesson","multi-form-data请求体"));
        result.push(new Item("body",req.body));
    } else {
        result.push(new Item("error","这个参数不认识"));
    }
    res.send(result);
});

接口测试

请使用接口调试工具,带上JSON请求体,去POST访问 localhost:8080/request/data/body/kind,修改不同的kind,看看它们的返回结果

获取路径参数

基础

路径参数是指 ‘/url?id=1&name=evanp’ 这种url中的id和name,是明文的不具有隐私性
可以通过 req.query获取

app.post('/request/data/query/info',checkQuery, (req, res)=> {
    res.send(req.query);
});

尝试用接口调试工具访问 localhost:8080/request/data/query/info,并携带上任意的query参数

Query预检

在实际场景中,每个接口会指定需要哪些名字的query参数,假设上面的接口需要id和name,则需要保证前端确实给接口传递了这两个query参数,express没有像springboot那样在入参的时候就可以规定检验,我们必须亲自对传过来的query进行检验。而这部分检验的操作不建议包含在我们接口的主体回调函数内,而应作为一个中间件,在回调之前就完成检验:

定义一个检查query的函数,判断是否有id和name,是的话继续,不是的话直接返回错误信息

function checkQuery(req,res,next) {
    if (req.query.id == undefined ||
        req.query.id == null ||
        req.query.name == undefined ||
        req.query.name == null){
        res.send({"msg": "query不齐全"});
    } else {
        next();
    }
}

在接口入参时引入该中间件函数

app.post('/request/data/query/info',checkQuery, (req, res)=> {
    res.send(req.query);
});

尝试用接口调试工具访问 localhost:8080/request/data/query/info,并比较不携带id,name和携带了id,name的返回结果

获取请求体

JSON请求体

引入以下代码一次即可

app.use(express.json({type: 'application/json'}));

表单(x-www-form-urlencoded)

x-www-form-urlencode将表单数据编码为URL形式的字符串

引入以下代码一次即可

app.use(express.urlencoded({extended: true}));

关于extended参数,是指将(URL编码字符串形式的)表单数据解析为简单对象还是深度嵌套对象.
什么意思呢?就比如当extended=false时,表单里是这么传数据的:
其中,有两个相同的键名: 比如传了2个x
解析后该字段的指将是所有它们的值的数组集合:x=1&x=2 -> {'x': ['1','2']},即便2个x都为1,也是数组: {'x': ['1','1']}
其中,又有的键名是以对象属性格式传递的,比如下图的user[uname]:
表单传嵌套对象
假如我们在api调试工具访问之前那个body/form-urlencode接口,同时以表单方式传输了这两种情况的数据,将得到这样的返回结果:

[
    {
        "name": "lesson",
        "value": "form-urlencode请求体"
    },
    {
        "name": "body",
        "value": {
            "user[uname]": "evanp",
            "user[passwd]": "iloveu",
            "x": [
                "1",
                "2"
            ]
        }
    }
]

当extended=true时,则是:

[
    {
        "name": "lesson",
        "value": "form-urlencode请求体"
    },
    {
        "name": "body",
        "value": {
            "user": {
                "uname": "evanp",
                "passwd": "iloveu"
            },
            "x": [
                "1",
                "2"
            ]
        }
    }
]

通过对比我们可以发现,extended=false时express比较憨,不会智能解析user到一个对象上去;智能解析的用处,我想大概是省的我们手动一条条注入属性到对象上去了

表单验证

对于请求参数我们有验证的需求,同样的,表单验证自然也会有,甚至可能需求性更高,因为需要考虑到安全问题
如果没有什么特殊要求,可以自己写一个中间件函数来检查表单,如果有比较高级的需求,可以借助线程的js库,如express-validator

表单(multi-form-data)

这个是可以一边传字符串,还可以传文件的表单,其实就是基础表单的一个升级版

需要事先安装multer依赖: npm install multer
引入依赖中间件:

const multer = require('multer');
const uploads = multer();

在需要接收文件的接口引入该中间件uploads:

app.post('/request/data/body/:kind', uploads.any(), function (req, res) 

在主体回调函数中通过req.files可以获取到所有的文件:

console.log(req.files); //写在multi-form-data分支下,方便区分

测试接口

使用api调试工具的复合表单携带文件发送请求到 body/multi-form-data 接口,查看我们的控制台:

[
  {
    fieldname: 'file',
    originalname: 'C.jpeg',
    encoding: '7bit',
    mimetype: 'image/jpeg',
    buffer: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48 00 48 00 00 ff db 00 43 00 0a 07 08 09 08 06 0a 09 08 09 0c 0b 0a 0c 0f 1a 11 0f 0e 0e 0f 1f 16 18 13 ... 9752 more bytes>,
    size: 9802
  }
]

是的,我刚刚传了一张名为 C.jpeg 的图片到服务器

下一节-响应

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大学计算机专业实习心得报告13篇

大学计算机专业实习心得报告&#xff08;篇1&#xff09; 通过理论联系实际&#xff0c;巩固所学的知识&#xff0c;提高处理实际问题的能力&#xff0c;为顺利毕业进行做好充分的准备&#xff0c;并为自己能顺利与社会环境接轨做准备。通过这次实习&#xff0c;使我们进一步理…

chatgpt赋能python:如何用Python创建优秀的项目

如何用Python创建优秀的项目 Python是一种功能强大的编程语言&#xff0c;可用于创建各种不同类型的项目。本文将介绍如何使用Python创建优秀的项目&#xff0c;并包括一些有用的技巧和工具。在本文中&#xff0c;我们将着重讨论如何优化我们的Python项目以获得更好的SEO排名。…

Gitlab 服务器搭建

引言 GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务。安装方法是参考GitLab在GitHub上的Wiki页面。Gitlab是被广泛使用的基于git的开源代码管理平台, 基于Ruby on Rails构建, 主要针对软件开发过程中…

C语言:求输入的两个数的最小公倍数

题目&#xff1a; 求输入的两个数的最小公倍数 思路一&#xff1a;普通方法 &#xff08;思路简单&#xff0c;效率较低&#xff09; 总体思路&#xff1a; &#xff08;一&#xff09;. 输入两个数&#xff1a;a 和 b&#xff0c; 使用 三目表达式 把较大值 取出 &#xff…

[元带你学: eMMC协议详解 17] eMMC 安全方案 之 RPMB(Replay Protected Memory Block 重放保护内存块)

依JEDEC eMMC 5.1及经验辛苦整理&#xff0c;付费内容&#xff0c;禁止转载。 所在专栏 《元带你学: eMMC协议详解》 内容摘要 全文 6300 字&#xff0c; 主要内容有 目录 1 概念 2 容量大小 3 重放保护的原理 4 不同访问类型流程 4.1. 写认证密钥&#xff08;write Au…

coder oss 真正私有化部署的云端开发环境,nas也可以装

先看效果&#xff1a; 主界面&#xff0c;显示了你有那些工作空间 某个工作空间&#xff0c;我这里集成了web版vscode&#xff0c;也可以使用本地的vscode和其他开发IDE 有独立的终端和集成webide 以后就可以一个ipad都可以写代码了&#xff1b; 下面是平台搭建过程&#xff0…

C语言入门基础知识(万字笔记)

一、前言部分 本篇文章&#xff0c;将会主要介绍c语言的基本数据类型、基本运算符、语句&#xff0c;三大结构、数组、指针、宏定义等内容 二、具体部分 1、基本数据类型 1、基本数据类型 在C语言中&#xff0c;承载一系列信息的数字或中字符都属于数据类型&#xff0c;计算…

产品设计.B端产品vsC端产品

一、用户群体 01、B端&#xff1a;一般是多角色群体、多维度&#xff0c;一般是3个维度&#xff0c;决策者&#xff08;老板&#xff09;、管理者&#xff08;财务、业务部门负责人&#xff09;和执行者&#xff08;使用的用户&#xff09;。 02、C端&#xff1a;群体相对单一…

K8s 中 port, targetPort, NodePort的区别

看1个例子&#xff1a; 我们用下面命令去创建1个pod2&#xff0c; 里面运行的是1个nginx kubectl create deployment pod2 --imagenginx当这个POD被创建后&#xff0c; 其实并不能被外部访问&#xff0c; 因为端口映射并没有完成. 我们用下面这个命令去创建1个svc &#xff…

msvcp140.dll是什么?怎么解决电脑提示msvcp140.dll丢失的问题?(分享解决方法)

msvcp140.dll是动态链接库文件&#xff0c;是一种不可执行的二进制程序文件&#xff0c;允许程序共享执行特殊任务所需要的代码和其他资源。程序可根据DLL文件中的指令打开、启用、查询、禁用和关闭驱动程序。 很多小伙伴在使用电脑软件的时候&#xff0c;有一些问题会搞不明白…

C语言之枚举联合

一、枚举 枚举顾名思义就是&#xff1a;列举 。 即把可能的取值一一列举出来 &#xff08;一&#xff09;枚举类型的定义 这里我们直接上代码&#xff1a; //枚举类型 #include <stdio.h>enum Sex//性别 {//枚举的可能取值-常量MALE 2,FEMALE 4,SECRET 8//以上为给…

LAMP架构及搭建LAMP+Discuz论坛

LAMP架构及搭建LAMPDiscuz论坛的流程 1、LAMP架构概述2、LAMP各组件的作用3、LAMP的安装顺序4、LAMP的数据流向5、编译安装Apache5.1 关闭防火墙和slinux&#xff0c;将安装Apache所需软件包传到/opt目录下并解压5.2 安装环境依赖包5.3 选择Apache软件模块5.4 编译和安装5.5 优…

使用 Sa-Token 实现 [记住我] 模式登录、七天免登录

一、需求分析 如图所示&#xff0c;一般网站的登录界面都会有一个 [记住我] 按钮&#xff0c;当你勾选它登录后&#xff0c;即使你关闭浏览器再次打开网站&#xff0c;也依然会处于登录状态&#xff0c;无须重复验证密码&#xff1a; 本文将详细介绍在 Sa-Token中&#xff0c;…

移动机器人底盘-四轮差速模型(四轮独立)

移动机器人底盘-四轮差速模型 文章目录 移动机器人底盘-四轮差速模型1. 四轮差速模型原理2. 工程实践2.1 Python实现2.2 C实现 1. 四轮差速模型原理 四轮差速模型底盘实例如下图所示。对于底盘的前轮和后轮来说&#xff0c;其速度是同步的&#xff0c;那么在理想条件下&#x…

PHY芯片的使用(一)之基本概念讲解(MII相关)2

今天想和大家交流一下MAC和PHY之间的接口MII。 MII(Media Independent Interface )是介质无关接口。MII接口定义了在MAC层和物理层之间传送数据和控制状态等信息的接口&#xff0c;它是10M和100M兼容的接口&#xff0c;经过扩展后还可以用于1000M的MAC层与物理层的接口&#x…

【libdatachannel】Transport的设计实现

作为ice传输实现的基类 具有实际的作用。 D:\XTRANS\thunderbolt\ayame\ZHB_LIB_DATACHANNEL\src\impl\transport.cpp 最重要的是封装了对impl的调用 Transport 比较牛,抽象了传输的基础能力 发送(调用ice接口发送) send(message_ptr message);接收(通过ice收到后使用回调方…

msvcp140.dll下载,无法启动此程序,因为计算机中丢失msvcp140.dll的解决方法

msvcp140.dll是动态链接库文件&#xff0c;是一种不可执行的二进制程序文件&#xff0c;允许程序共享执行特殊任务所需要的代码和其他资源。程序可根据DLL文件中的指令打开、启用、查询、禁用和关闭驱动程序。 很多小伙伴在使用电脑软件的时候&#xff0c;有一些问题会搞不明白…

layui框架学习(27:弹出层模块_其它用法)

除了前几篇文章介绍的弹出框类型外&#xff0c;layui的layer弹出层模块还支持相册框和tab框&#xff0c;所谓相册框即点击图片或按钮后会出现一个类似相册的页面单独浏览、切换图片&#xff0c;而tab框是指弹出框的显示形式类似于Winform中的TabControl控件&#xff0c;能以选项…

如何把一个 Git 仓库的分支加入另一个无关的 Git 仓库

文章目录 笔者需要将两个无关的 Git 仓库合并&#xff0c;也就是把一个 Git 仓库的分支加入另一个无关的 Git 仓库。笔者琢磨了一下之后就实现了。方法如下。 笔者的运行环境&#xff1a; git version 2.37.0.windows.1 TortoiseGit 2.11.0.0 IntelliJ IDEA 2023.1.1 (Ultima…

vue2_markdown的内容目录生成

文章目录 ⭐前言⭐引入vue-markdown&#x1f496; 全局配置&#x1f496; 渲染选项&#x1f496; 取出markdown的标题层级 ⭐结束 ⭐前言 大家好&#xff01;我是yma16&#xff0c;本文分享在vue2的markdown文本内容渲染和目录生成 背景&#xff1a; 优化个人博客功能&#xf…