├── node_modules
├── prisma
│ ├── migrations
│ ├── schema.prisma
│ └── seed.ts
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ ├── main.ts
│ ├── articles
│ └── prisma
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── README.md
├── .env
├── docker-compose.yml
├── nest-cli.json
├── package-lock.json
├── package.json
├── tsconfig.build.json
└── tsconfig.json

此存儲庫中值得關(guān)注的文件和目錄包括:

注意:有關(guān)這些組件的更多信息,請閱讀本教程系列的第一部分。

執(zhí)行輸入驗證

為了執(zhí)行輸入驗證,您將借助 NestJS 中的管道功能。管道針對路由處理程序正在處理的參數(shù)進(jìn)行操作。在路由處理程序之前,Nest 會調(diào)用管道,而管道則接收發(fā)往路由處理程序的參數(shù)。管道的功能多樣,不僅可以驗證輸入,還可以向輸入添加字段等。盡管 NestJS 提供了一些內(nèi)置的管道,但您同樣可以創(chuàng)建自定義管道以滿足特定需求。

管道有兩個典型的用例:

NestJS 的驗證管道會檢查傳遞給路由的參數(shù)。若參數(shù)有效,管道會將其原封不動地傳遞給路由處理程序;若參數(shù)違反任何指定的驗證規(guī)則,管道則會拋出異常。

以下示意圖展示了驗證管道在任意路由(如 /example)中的工作原理。

在本節(jié)中,您將重點介紹驗證使用案例。

全局設(shè)置 ValidationPipe

為了執(zhí)行輸入驗證,您將利用 NestJS 內(nèi)置的?ValidationPipeValidationPipe?提供了一種高效的方式,可以對所有傳入的客戶端請求有效負(fù)載自動執(zhí)行驗證規(guī)則。這些驗證規(guī)則是通過?class-validator?包中的裝飾器來聲明的。

要使用此功能,您需要向項目添加兩個包:

npm install class-validator class-transformer

class-validator 包提供了用于驗證輸入數(shù)據(jù)的裝飾器,而 class-transformer 包則提供了用于將輸入數(shù)據(jù)轉(zhuǎn)換為所需形式的裝飾器。這兩個包都與 NestJS 的管道功能實現(xiàn)了良好的集成。

現(xiàn)在,您需要在 main.ts 文件中導(dǎo)入這些包,并通過 app.useGlobalPipes 方法使 ValidationPipe 在您的應(yīng)用程序中全局可用。

// src/main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
const app = await NestFactory.create(AppModule);

app.useGlobalPipes(new ValidationPipe());

const config = new DocumentBuilder()
.setTitle('Median')
.setDescription('The Median API description')
.setVersion('0.1')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);

await app.listen(3000);
}
bootstrap();

將驗證規(guī)則添加到CreateArticDto

現(xiàn)在,您需要使用?class-validator?包中的驗證修飾器來增強(qiáng)?CreateArticleDto。以下是您需要應(yīng)用的驗證規(guī)則:

接下來,請打開 src/articles/dto/create-article.dto.ts 文件,并將其內(nèi)容替換為符合上述規(guī)則的代碼。

// src/articles/dto/create-article.dto.ts

import { ApiProperty } from '@nestjs/swagger';
import {
IsBoolean,
IsNotEmpty,
IsOptional,
IsString,
MaxLength,
MinLength,
} from 'class-validator';

export class CreateArticleDto {
@IsString()
@IsNotEmpty()
@MinLength(5)
@ApiProperty()
title: string;

@IsString()
@IsOptional()
@IsNotEmpty()
@MaxLength(300)
@ApiProperty({ required: false })
description?: string;

@IsString()
@IsNotEmpty()
@ApiProperty()
body: string;

@IsBoolean()
@IsOptional()
@ApiProperty({ required: false, default: false })
published?: boolean = false;
}

這些驗證規(guī)則將被自動選取并應(yīng)用于您的路由處理程序。使用裝飾器進(jìn)行驗證的一個顯著優(yōu)點是,this?關(guān)鍵字仍然是端點所有參數(shù)的單一事實來源,因此您無需定義單獨的驗證類。例如,對于?CreateArticleDto?在?POST /articles?路由中的應(yīng)用,驗證規(guī)則會自動生效。

為了測試您設(shè)置的驗證規(guī)則,您可以嘗試通過端點創(chuàng)建一個文章,但故意使用非常短的占位符作為標(biāo)題,如下所示:POST /articles 請求體中僅包含 title 字段且其值很短。

{
"title": "Temp",
"description": "Learn about input validation",
"body": "Input validation is...",
"published": false
}

您應(yīng)該會收到 HTTP 400 錯誤響應(yīng),并在響應(yīng)正文中收到有關(guān)違反了驗證規(guī)則的詳細(xì)信息。

帶有描述性錯誤消息的 HTTP 400 響應(yīng)

下圖展示了 ValidationPipe 在后臺針對 /articles 路由的無效輸入所執(zhí)行的操作。

使用 ValidationPipe 的輸入驗證流程

從客戶端請求中去除不必要的屬性

這確保 API 安全和穩(wěn)定的重要步驟。這定義了創(chuàng)建新文章時需要發(fā)送到端點的必要屬性。對于創(chuàng)建文章的端點(POST /articles),我們使用 CreateArticleDTO 來明確這些屬性。同樣地,對于更新文章的端點(PATCH /articles/{id}),我們使用 UpdateArticleDTO 來指定哪些屬性可以更新。

然而,目前這兩個端點存在一個潛在問題:客戶端可以發(fā)送 DTO 中未定義的額外屬性。這可能會引發(fā)不可預(yù)見的錯誤或構(gòu)成安全風(fēng)險。例如,攻擊者可能會嘗試傳遞無效的值或惡意字段給終端節(jié)點。由于 TypeScript 的類型信息在運行時是不可用的,您的應(yīng)用程序無法自動識別并拒絕這些不在 DTO 中定義的字段。

舉個例子,嘗試向POST /articles終端節(jié)點發(fā)送以下請求:

{
"title": "example-title",
"description": "example-description",
"body": "example-body",
"published": true,
"createdAt": "2010-06-08T18:20:29.309Z",
"updatedAt": "2021-06-02T18:20:29.310Z"
}

這樣,您可能會不小心注入無效值。例如,您可能會創(chuàng)建一篇文章,其中包含了像 precedesupdatedAt 或 createdAt 這樣沒有實際意義或不應(yīng)該由客戶端指定的字段/屬性。

為了防止這種情況發(fā)生,您需要從客戶端請求中過濾掉任何不必要的字段/屬性。幸運的是,NestJS 提供了一個現(xiàn)成的解決方案。您只需在初始化應(yīng)用程序時,為?ValidationPipe?傳遞一個選項,將?whitelist?設(shè)置為?true?即可。

// src/main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
const app = await NestFactory.create(AppModule);

app.useGlobalPipes(new ValidationPipe({ whitelist: true }));

const config = new DocumentBuilder()
.setTitle('Median')
.setDescription('The Median API description')
.setVersion('0.1')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);

await app.listen(3000);
}
bootstrap();

將此選項設(shè)置為 true 后,ValidationPipe 會自動移除所有未列入白名單的屬性。這里的“non-whitelisted”指的是那些沒有添加驗證裝飾器的屬性。請注意,此選項會過濾掉所有沒有驗證裝飾器的屬性,即使它們在 DTO(數(shù)據(jù)傳輸對象)中已被定義。

現(xiàn)在,當(dāng)客戶端請求包含任何未經(jīng)驗證的字段/屬性時,NestJS 會自動剝離這些字段,從而避免之前提到的安全漏洞。

注意:NestJS 提供了高度的可配置性。所有可用的配置選項都詳細(xì)記錄在 NestJS 官方文檔中。如果標(biāo)準(zhǔn)配置無法滿足您的需求,您還可以為應(yīng)用程序構(gòu)建自定義的驗證管道。

轉(zhuǎn)換動態(tài) URL 路徑中的參數(shù):ParseIntPipe

在您的 API 中,GET /articles/{id}PATCH /articles/{id}?和?DELETE /articles/{id}?這三個端點目前都接受一個?id?參數(shù)作為 URL 路徑的一部分。NestJS 默認(rèn)會將路徑中的參數(shù)解析為字符串。然而,在將這些參數(shù)傳遞給?ArticlesService?之前,您需要在應(yīng)用程序代碼中將這些字符串強(qiáng)制轉(zhuǎn)換為數(shù)字。為了簡化這一過程,您可以使用?ParseIntPipe。這個管道會自動將路徑參數(shù)從字符串轉(zhuǎn)換為整數(shù),從而確保類型安全并減少出錯的可能性。

// src/articles/articles.controller.ts

@Delete(':id')
@ApiOkResponse({ type: ArticleEntity })
remove(@Param('id') id: string) { // id is parsed as a string
return this.articlesService.remove(+id); // id is converted to number using the expression '+id'
}

由于 id 被定義為字符串類型,Swagger API 在生成的 API 文檔中也會將此參數(shù)標(biāo)記為字符串類型。然而,這種表示可能不夠直觀,甚至在某些情況下是不正確的,特別是當(dāng) id 實際上應(yīng)該表示一個數(shù)字或特定格式的標(biāo)識符時。

您可以在 NestJS 中使用管道來自動將 id 轉(zhuǎn)換為數(shù)字,而無需在路由處理程序中手動執(zhí)行此轉(zhuǎn)換。為此,您可以將 ParseIntPipe(一個內(nèi)置管道)添加到以下三個端點的控制器路由處理程序中,以便對 id 參數(shù)進(jìn)行自動轉(zhuǎn)換。

// src/articles/articles.controller.ts

import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
NotFoundException,
ParseIntPipe,
} from '@nestjs/common';

export class ArticlesController {
// ...

@Get(':id')
@ApiOkResponse({ type: ArticleEntity })
findOne(@Param('id', ParseIntPipe) id: number) {
return this.articlesService.findOne(id);
}

@Patch(':id')
@ApiCreatedResponse({ type: ArticleEntity })
update(
@Param('id', ParseIntPipe) id: number,
@Body() updateArticleDto: UpdateArticleDto,
) {
return this.articlesService.update(id, updateArticleDto);
}

@Delete(':id')
@ApiOkResponse({ type: ArticleEntity })
remove(@Param('id', ParseIntPipe) id: number) {
return this.articlesService.remove(id);
}
}

ParseIntPipe?會攔截字符串類型的參數(shù),并在將其傳遞給路由處理程序之前,自動將其解析為數(shù)字。此外,它還具有在 Swagger 文檔中將參數(shù)正確記錄為數(shù)字類型的優(yōu)勢。

總結(jié)和結(jié)束語

祝賀您!在本教程中,您對一個現(xiàn)有的 REST API 進(jìn)行了增強(qiáng),具體完成了以下任務(wù):

您可能已經(jīng)發(fā)現(xiàn),NestJS 大量使用了裝飾器。這是其設(shè)計中的一個核心特點,旨在通過裝飾器來處理各種橫切關(guān)注點,從而提高代碼的可讀性和模塊化程度。因此,在控制器和服務(wù)方法中,您無需編寫大量的樣板代碼來執(zhí)行驗證、緩存、日志記錄等操作。

您可以在 GitHub 存儲庫的?end-validation?分支中找到本教程的完整代碼。如果您在代碼實現(xiàn)過程中遇到任何問題,歡迎在存儲庫中提出疑問或提交 Pull Request。當(dāng)然,您也可以直接在 Twitter 上與我取得聯(lián)系。

原文鏈接:https://www.prisma.io/blog/nestjs-prisma-validation-7D056s1kOla1

熱門推薦
一個賬號試用1000+ API
助力AI無縫鏈接物理世界 · 無需多次注冊
3000+提示詞助力AI大模型
和專業(yè)工程師共享工作效率翻倍的秘密
返回頂部
上一篇
使用 AWS Gateway 和 Python 構(gòu)建 REST API
下一篇
使用 NestJS 和 Prisma 構(gòu)建 REST API:錯誤處理
国内精品久久久久影院日本,日本中文字幕视频,99久久精品99999久久,又粗又大又黄又硬又爽毛片
成人欧美一区二区三区在线播放| 裸体健美xxxx欧美裸体表演| wwwwww.欧美系列| 亚洲国产精品一区二区久久恐怖片 | 日本v片在线高清不卡在线观看| 欧美在线999| 首页欧美精品中文字幕| 欧美男人的天堂一二区| 奇米综合一区二区三区精品视频| 日韩一区二区三区免费观看| 精品一区二区免费| 日韩码欧中文字| 欧美日韩在线观看一区二区| 强制捆绑调教一区二区| 久久久久99精品一区| 欧美日韩国产不卡| 欧美日韩国产美| 色94色欧美sute亚洲线路一久| 欧美日韩中文国产| 亚洲人成影院在线观看| 日韩电影在线看| 欧美性受xxxx黑人xyx| 国产欧美精品一区aⅴ影院 | 久久久亚洲欧洲日产国码αv| 亚洲自拍欧美精品| 精品国产髙清在线看国产毛片| 国产精品护士白丝一区av| 蜜乳av一区二区| 欧美精品一区二区三区蜜桃 | 高清国产一区二区| 亚洲欧美偷拍三级| 欧美羞羞免费网站| 欧美一区二区成人6969| 久久99国产精品久久99| 亚洲午夜视频在线观看| 欧洲一区二区三区免费视频| 国产精品白丝av| 亚洲国产欧美日韩另类综合| a美女胸又www黄视频久久| av在线播放成人| 91在线视频在线| 一本大道久久a久久综合婷婷| 高清国产一区二区三区| 日韩一区二区三区在线视频| 午夜精品一区在线观看| 亚洲欧美日韩国产综合在线| 韩国女主播一区二区三区| 777亚洲妇女| 国产精品视频在线看| 国产精品18久久久久久久久久久久| 国产精品久久久久久久久快鸭| 欧美日韩电影一区| 99久精品国产| 成人app下载| av激情成人网| 99re这里都是精品| 91小宝寻花一区二区三区| 成人午夜电影网站| 91色乱码一区二区三区| 色噜噜狠狠成人中文综合| 91首页免费视频| 欧美吞精做爰啪啪高潮| 在线播放中文一区| 欧美v日韩v国产v| 欧美精品一区二区三区蜜臀 | 日韩理论电影院| 一区二区三区自拍| 午夜不卡av在线| 免费高清在线一区| 国产精品99精品久久免费| 国产寡妇亲子伦一区二区| 国产一区二区中文字幕| 大胆亚洲人体视频| 欧美色视频一区| 久久综合中文字幕| 亚洲天天做日日做天天谢日日欢| 一区二区三区在线看| 视频一区二区三区入口| 国产精品一二三区| 欧美日韩成人一区| 国产天堂亚洲国产碰碰| 一区二区三区四区不卡在线| 久久er99热精品一区二区| 91小视频在线| 久久人人97超碰com| 亚洲精品国产第一综合99久久| 午夜av一区二区| www.日韩精品| 国产午夜精品一区二区三区嫩草| 亚洲午夜激情av| 成人综合婷婷国产精品久久| 日韩欧美你懂的| 亚洲综合图片区| 不卡av免费在线观看| 日韩免费一区二区三区在线播放| 综合网在线视频| 国产91清纯白嫩初高中在线观看| 欧美日韩在线直播| 亚洲视频一二区| 成人福利视频在线| 久久嫩草精品久久久精品一| 日韩国产精品91| 欧美日韩一区二区三区四区五区| 中文字幕免费不卡| 国产成人8x视频一区二区| 精品国产凹凸成av人网站| 爽好多水快深点欧美视频| 91高清在线观看| 亚洲综合男人的天堂| 日本高清无吗v一区| 一区二区三区在线影院| 色婷婷综合在线| 亚洲成人在线网站| 欧美视频一区二区在线观看| 亚洲啪啪综合av一区二区三区| 成人性色生活片免费看爆迷你毛片| 欧美精品一区二区在线播放| 激情久久五月天| 国产日韩v精品一区二区| 国产精品1024| 国产精品丝袜久久久久久app| 丰满亚洲少妇av| 亚洲视频图片小说| 欧美午夜理伦三级在线观看| 亚洲.国产.中文慕字在线| 欧美精品高清视频| 久久99精品国产麻豆不卡| 国产欧美一区二区精品性色| 97久久精品人人做人人爽| 国产色产综合产在线视频| 欧美怡红院视频| 成人app网站| 久久久.com| 不卡av在线免费观看| 一区二区三区在线免费| 6080国产精品一区二区| 国产乱人伦精品一区二区在线观看| 亚洲国产精品黑人久久久| 国产精品久久国产精麻豆99网站| 久久亚洲一区二区三区明星换脸 | 一区二区三区日韩精品| 7777精品伊人久久久大香线蕉超级流畅| 亚洲国产va精品久久久不卡综合| 在线电影院国产精品| 国产成人综合网站| 五月婷婷综合激情| 国产精品国产精品国产专区不片| 欧美在线免费观看亚洲| 日韩精品综合一本久道在线视频| 美国十次综合导航| 亚洲最大成人网4388xx| 欧美一区二区啪啪| 91在线视频免费观看| 久久不见久久见免费视频7| 亚洲一区二区三区四区中文字幕 | 精品一区二区在线免费观看| 一区二区三区四区五区视频在线观看| 欧美一级生活片| 一本一道久久a久久精品| 国产成人综合亚洲网站| 日韩不卡免费视频| 亚洲在线一区二区三区| 国产三级精品三级| 亚洲精品一区二区三区蜜桃下载| 欧美性猛交xxxx乱大交退制版 | 不卡av在线网| 成人网页在线观看| 亚洲一区二区三区小说| 国产精品成人免费在线| 欧美精品一区二区在线播放 | 国产精品1024久久| 精品国产凹凸成av人网站| 欧美另类变人与禽xxxxx| 不卡一区中文字幕| 成人亚洲一区二区一| 国产麻豆精品久久一二三| 狠狠色丁香婷婷综合久久片| 加勒比av一区二区| 国内精品伊人久久久久av一坑 | 亚洲欧美日韩系列| 中文字幕视频一区| 国产精品网站一区| 国产精品网友自拍| 一区二区三区四区蜜桃 | 亚洲一区免费视频| 首页国产丝袜综合| 日韩和欧美一区二区三区| 青青草成人在线观看| 精品亚洲国产成人av制服丝袜| 国内精品久久久久影院色| 国产激情91久久精品导航| 国产一区二区电影| 97se亚洲国产综合自在线观| 色香色香欲天天天影视综合网| 欧美日韩免费高清一区色橹橹 | 中文字幕日韩av资源站| 亚洲国产一区二区视频| 国模无码大尺度一区二区三区 | 色狠狠一区二区三区香蕉| 欧美不卡123|