NestJS中用Class Validator校验消息文本不包含URL的问题
解决NestJS DTO中消息文本的URL校验问题
你的问题出在正则表达式的转义处理和匹配范围上,以下是具体的修复方案:
1. 修复原有正则的核心问题
原来的正则字符串中,\b在JavaScript里会被转义为退格字符,导致正则的单词边界匹配失效,无法正确识别URL的协议前缀。同时原有规则没有覆盖www.开头的无协议URL,也没考虑大小写问题。
修改后的DTO代码如下:
import { ApiProperty } from '@nestjs/swagger'; import { Matches, MaxLength } from 'class-validator'; export class CreateMessageInput { @ApiProperty() userId: string; @ApiProperty() @MaxLength(200) @Matches( /^(?!.*(?:https?:\/\/|ftp:\/\/|file:\/\/|www\.)[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|]).*$/i, { message: '消息文本不能包含链接或URL' } ) text: string; }
关键改进点:
- 使用正则字面量(
/.../)替代字符串,避免双重转义问题 - 添加
www.匹配规则,覆盖无协议的常见URL - 加上
/i标志,忽略大小写匹配 - 自定义错误提示,提升用户体验
2. 更灵活的自定义校验器方案
如果需要覆盖更多边缘场景(比如example.com这类既无协议也无www的域名),推荐使用自定义校验器,扩展性更强:
第一步:创建自定义校验器
import { ValidationOptions, registerDecorator, ValidationArguments } from 'class-validator'; export function NoUrl(validationOptions?: ValidationOptions) { return function (object: Object, propertyName: string) { registerDecorator({ name: 'noUrl', target: object.constructor, propertyName: propertyName, options: validationOptions, validator: { validate(value: string) { // 匹配常见URL格式,包括无协议域名 const urlRegex = /(https?:\/\/|ftp:\/\/|file:\/\/|www\.|[\w-]+\.(com|cn|net|org|io))/i; return !urlRegex.test(value); }, defaultMessage() { return '消息文本不能包含链接或URL'; }, }, }); }; }
第二步:在DTO中使用自定义校验器
import { ApiProperty } from '@nestjs/swagger'; import { MaxLength } from 'class-validator'; import { NoUrl } from './no-url.validator'; export class CreateMessageInput { @ApiProperty() userId: string; @ApiProperty() @MaxLength(200) @NoUrl() text: string; }
这样可以根据业务需求随时扩展正则规则,比如添加更多顶级域名、匹配IP地址形式的URL等。
内容的提问来源于stack exchange,提问作者Bowis
相关产品推荐
相关产品推荐

