NestJS 中 HTTP请求与响应

1. 前言

上一篇《Nest 快速入门》主要介绍NestJS的定位和快速入门例子,本文详细说说怎么在 NestJS 中进行 HTTP 请求和响应。

2. HTTP 协议回顾

2.1 HTTP 请求数据格式

举例:

规则:

2.2 HTTP 响应数据格式

举例:

规则:

3. 路由控制器

NestJS 控制器的目的是接收应用程序的特定请求,路由机制控制哪个控制器接收哪些请求。通常,每个控制器都有多个路由,并且不同的路由可以执行不同的操作。

通过装饰器和类创建控制器,装饰器将类与所需的元数据关联起来,并使 Nest 能够创建路由映射(将请求绑定到相应的控制器)。

  1. 通过 Nest CLI 工具,新建一个部门模块
js 复制代码
nest g mo dept

生成文件如下:

js 复制代码
import { Module } from '@nestjs/common';
import { DeptController } from './dept.controller';

@Module({
  controllers: [DeptController],
})
export class DeptModule {}
  1. 新建 Controller 文件
js 复制代码
 nest g co dept

在生成的文件添加 findAll 方法

js 复制代码
// src/dept/deptController.ts
import { Controller, Get } from '@nestjs/common';

@Controller('/depts')
export class DeptController {
  @Get()
  findAll(): Array<{ name: string; id: number }> {
    return [
      {
        name: '学工部',
        id: 1,
      },
      {
        name: '教研部',
        id: 2,
      },
    ];
  }
}

@Get() 表示当前请求的方法是 Get 方法,将会匹配 /depts 请求,然后执行 findAll() 方法,该方法返回的数据就是接口返回的数据,NestJS 会自动序列化为 JSON 字符串,并响应给客户端。

  1. dept 模块在 app 中注册如下:
js 复制代码
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DeptModule } from './dept/dept.module';

@Module({
  imports: [DeptModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

此时请求如下

4. NestJS 中的 HTTP 请求

Nest 为所有标准 HTTP 方法提供了装饰器:@Get()@Post()@Put()@Delete()@Patch()@Options()@Head()

4.1 简单参数

下面两种跟随 url 上的参数

  • urlParam 参数:比如根据 id 查询部门 /depts/:id
  • query:分页查询员工数据 /emps?page=1&pageSize=10

4.1.1 urlParam

1.编写代码

js 复制代码
import { Controller, Get, Param } from '@nestjs/common';

@Controller('/depts')
export class DeptController {
  @Get()
  findAll(): Array<{ name: string; id: number }> {
    return [
      {
        name: '学工部',
        id: 1,
      },
      {
        name: '教研部',
        id: 2,
      },
    ];
  }

  @Get(':id')
  findOne(@Param('id') id: string): { name: string; id: string } {
    return {
      name: '学工部',
      id,
    };
  }
}

2.验证请求

4.1.2 query

1.重新构建一个员工模块

sh 复制代码
nest g mo emp # 创建模块
nest g co emp # 创建控制器
nest g s emp # 创建业务服务,目前没用到

2.编写获取查询参数,通过 @Query 装饰器获取

js 复制代码
import { Controller, Get, Query } from '@nestjs/common';

@Controller('/emps')
export class EmpController {
  @Get()
  findAll(@Query('page') page: number, @Query('pageSize') pageSize: number) {
    return {
      pageSize,
      page,
      list: [],
    };
  }
}

3.验证

4.2 复杂参数

  • form urlencoded
  • json
  • form data

4.2.1 form urlencoded

form url encoded 通过 body 传输数据,也就是把 query 字符串放在了 body 里,同样需要做 url encode,指定 content type 为 application/x-www-form-urlencoded

js 复制代码
// src/dept/dept.controller.ts
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { CreateDeptDto } from './dto/create-dept.dto';

@Controller('/depts')
export class DeptController {
  @Post()
  addEmp(@Body() createDeptDto: CreateDeptDto) {
    return {
      name: createDeptDto.name,
    };
  }
}

使用 Nest @Body 装饰器接受,Nest 会解析并把数据注入到 dto 中,dto 是 data transfer object,就是用于封装传输的数据的对象。

js 复制代码
// src/dept/dto/create-dept.dto.ts
export class CreateDeptDto {
  name: string;
}

验证如下:

这种方式目前不太常见,通常使用 json 的方式进行新增。

4.2.2 json

json 需要指定 content-typeapplication/json ,内容会以 JSON 的方式传输:

后端代码不需要做改动,同样使用 @Body 进行接收,Nest 内部会根据 content type 区分解析方式。

前面两种适合传输文本数据,如果是复杂的二进制文件,则考虑使用 formData 进行传输。

4.2.3 formData

formData 通过 - - - - 作为 boundary 分隔的数据,主要用于传输文件。前端指定 content-type multipart/form-data ,并且用 FormData 对象来封装传输的内容。

这里实现上传图像功能,这个图像可以作为员工图像。

js 复制代码
 @Post()
  @UseInterceptors(
    AnyFilesInterceptor({
      dest: 'uploads/',
    }),
  )
  create(
    @Body() createEmptDto: CreateEmptDto,
    @UploadedFiles() files: Array<Express.Multer.File>,
  ) {
    console.log(createEmptDto);
    console.log(files);
    return {
      success: true,
    };
}

Nest 解析 form data 使用 FilesInterceptor 的拦截器,用 @UseInterceptors 装饰器启用,然后通过 @UploadedFiles 来取。非文件的内容,同样是通过 @Body 来取。

测试验证:

5. NestJS 中的 HTTP 响应

Controller 抓装饰器 声明的类上,会将方法返回值直接响应,如果返回值是对象或数组,将会转换为 JSON 格式响应。

其他情况,可以使用 @Res 获取响应对象,进行处理,Nest 的底层架构默认使用了 Express,这里的 Res 对象用法跟 Express 一致。

js 复制代码
@Controller('/www')
export class WWWController {
  @Get('')
  async query(@Req() req, @Res() res) {
    const { headers } = req;
    let platform = 'pc';
    if (headers['user-agent'].includes('Mobile')) {
      platform = 'mobile';
    }
    res.redirect(`/fopFePortalServices/www/${platform}`);
  }
}

小结

本文主要讲解了在 Nest 中主要使用 Controller 进行 HTTP 的请求与响应,通过 @Get@Post() 等装饰器实现路由声明,通过 @Param@Body 获取路由的参数,通过 @UploadedFiles 获取 formData 数据,并直接通过方法返回值响应数据给客户端。

相关推荐
FungLeo4 分钟前
node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示
前端·非对称加密·rsa 加密·node 后端
不知道写什么的作者7 分钟前
Flask快速入门和问答项目源码
后端·python·flask
雪芽蓝域zzs14 分钟前
JavaScript splice() 方法
开发语言·javascript·ecmascript
不灭锦鲤14 分钟前
xss-labs靶场第11-14关基础详解
前端·xss
不是吧这都有重名40 分钟前
利用systemd启动部署在服务器上的web应用
运维·服务器·前端
霸王蟹41 分钟前
React中巧妙使用异步组件Suspense优化页面性能。
前端·笔记·学习·react.js·前端框架
caihuayuan51 小时前
生产模式下react项目报错minified react error #130的问题
java·大数据·spring boot·后端·课程设计
Maỿbe1 小时前
利用html制作简历网页和求职信息网页
前端·html
一只码代码的章鱼1 小时前
Spring Boot- 2 (数万字入门教程 ):数据交互篇
spring boot·后端·交互
森叶1 小时前
Electron 主进程中使用Worker来创建不同间隔的定时器实现过程
前端·javascript·electron