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

相关推荐
万少5 分钟前
第五款 HarmonyOS 上架作品 奇趣故事匣 来了
前端·harmonyos·客户端
OpenGL11 分钟前
Android targetSdkVersion升级至35(Android15)相关问题
前端
rzl0227 分钟前
java web5(黑马)
java·开发语言·前端
Amy.Wang28 分钟前
前端如何实现电子签名
前端·javascript·html5
海天胜景30 分钟前
vue3 el-table 行筛选 设置为单选
javascript·vue.js·elementui
今天又在摸鱼31 分钟前
Vue3-组件化-Vue核心思想之一
前端·javascript·vue.js
君爱学习32 分钟前
RocketMQ延迟消息是如何实现的?
后端
蓝婷儿32 分钟前
每天一个前端小知识 Day 21 - 浏览器兼容性与 Polyfill 策略
前端
百锦再35 分钟前
Vue中对象赋值问题:对象引用被保留,仅部分属性被覆盖
前端·javascript·vue.js·vue·web·reactive·ref
jingling55539 分钟前
面试版-前端开发核心知识
开发语言·前端·javascript·vue.js·面试·前端框架