需求
需要对接口的异常响应码,手动设置message文本!!!
例如:项目中使用multer中间件实现文件上传,multer设置了文件大小限制,该中间件校验文件时错误(文件超出)会自动响应为:
status: 413
statusMessage: 'Playload Too Large'
// 响应数据
{
"message": "File too large",
"error": "Payload Too Large",
"statusCode": 413
}
但是我想自定义设置该message的文本,甚至是设置statusMessage文本
实现
通过局部异常过滤器实现
custom-exception.filter.ts
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
HttpStatus,
Logger,
} from '@nestjs/common';
/**
* 自定义异常过滤器
* 为指定响应码设置message文本
*
* 例子: 文件上传中间件校验文件大小, 失败会自动响应为413, message为File too large
* 我想将message设置为 '文件过大', 就可以使用该过滤器
*
* 使用方式: 在controller层接口函数上添加:
* @UseFilters(new CustomExceptionFilter(new CodeMessage(413, '文件过大')))
* @UseFilters(
* new CustomExceptionFilter([
* new CodeMessage(413, '文件过大'),
* new CodeMessage(415, '文件格式错误'),
* ]),
* )
* @UseFilters(new CustomExceptionFilter({ code: 413, message: '文件大小错误' }))
*
* (CodeMessage对象中: code用于匹配响应码, message为要设置的文本)
*/
@Catch()
export class CustomExceptionFilter implements ExceptionFilter {
// 允许传入对象或者对象数组
constructor(private readonly referenceData: CodeMessage | CodeMessage[]) {}
catch(exception: Error, host: ArgumentsHost) {
const ctx = host.switchToHttp(); // 获取请求上下文
const request = ctx.getRequest(); // 获取请求上下文中的request对象
const response = ctx.getResponse(); // 获取请求上下文中的response对象
// 获取异常状态码
const status =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
// 响应数据的错误码和错误信息
let code = 500;
let message = '服务器错误(Service Error)';
// 取传入数据中对应的code与message, 可能是数组或对象
if (Array.isArray(this.referenceData)) {
for (let i = 0; i < this.referenceData.length; i++) {
const item = this.referenceData[i];
if (item.code === status) {
code = item.code;
message = item.message;
break;
}
}
} else if (
Object.prototype.toString.call(this.referenceData) ===
'[object Object]' &&
this.referenceData.code === status
) {
code = this.referenceData.code;
message = this.referenceData.message;
}
// 响应数据
const errorResponse = {
code,
message,
errorMessage: exception.message,
};
// 将异常记录到logger中
Logger.error(`异常 >>>> 【${new Date()}】${request.method} ${request.url}`);
Logger.error(`query: ${JSON.stringify(request.query)}`);
Logger.error(`params: ${JSON.stringify(request.params)}`);
Logger.error(`body: ${JSON.stringify(request.body)}`);
Logger.error(`error: ${exception}`);
Logger.error(`errorResponse: ${JSON.stringify(errorResponse)}`);
// 设置返回的状态码, 请求头,发送错误信息
response.setHeader('Content-Type', 'application/json; charset=gb2312');
response.status(status);
// response.statusMessage = message;
response.send(errorResponse);
}
}
// 码对应消息
export class CodeMessage {
code: number;
message: string;
constructor(code: number, message: string) {
this.code = code;
this.message = message;
}
}
使用
/**
* 中间件实现上传
* @param file
*/
@Post('test')
@UseFilters(new CustomExceptionFilter(new CodeMessage(413, '文件过大')))
// @UseFilters(
// new CustomExceptionFilter([
// new CodeMessage(413, '文件过大'),
// new CodeMessage(415, '文件格式错误'),
// ]),
// )
// @UseFilters(new CustomExceptionFilter({ code: 413, message: '文件过大' }))
test() {
throw new HttpException('模拟异常', 413);
return 'OK';
}