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 数据,并直接通过方法返回值响应数据给客户端。

相关推荐
aPurpleBerry13 分钟前
JS常用数组方法 reduce filter find forEach
javascript
码农派大星。20 分钟前
Spring Boot 配置文件
java·spring boot·后端
GIS程序媛—椰子41 分钟前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0011 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端1 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x1 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
木舟10091 小时前
ffmpeg重复回听音频流,时长叠加问题
前端
杜杜的man1 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*1 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu1 小时前
Go语言结构体、方法与接口
开发语言·后端·golang