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

相关推荐
狸克先生9 分钟前
如何用AI写小说(二):Gradio 超简单的网页前端交互
前端·人工智能·chatgpt·交互
sinat_3842410912 分钟前
在有网络连接的机器上打包 electron 及其依赖项,在没有网络连接的机器上安装这些离线包
javascript·arcgis·electron
baiduopenmap24 分钟前
百度世界2024精选公开课:基于地图智能体的导航出行AI应用创新实践
前端·人工智能·百度地图
loooseFish32 分钟前
小程序webview我爱死你了 小程序webview和H5通讯
前端
郑祎亦35 分钟前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis
小牛itbull36 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i44 分钟前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
533_1 小时前
[vue] 深拷贝 lodash cloneDeep
前端·javascript·vue.js
本当迷ya1 小时前
💖2025年不会Stream流被同事排挤了┭┮﹏┭┮(强烈建议实操)
后端·程序员
guokanglun1 小时前
空间数据存储格式GeoJSON
前端