在NestJs中为单个控制器设置请求体大小限制

3

我希望为单个路由增加请求体大小限制,例如仅针对路由/uploads,并保持其余部分默认。

我知道你可以使用以下方法进行全局设置:

app.use(json({ limit: '50mb' }));

或者,在纯ExpressJS中,您可以使用以下代码:
router.use('/uploads', express.json({ limit: '50MB' }));

但是在NestJS中只有一个全局的app和控制器类。例如:
@Controller('uploads')
export class UploadController {
  constructor() {}

  @Post()
  create(...): Promise<any> {
    ...
  }
}

这个控制器的限制应该设置在哪里?

3个回答

8

实际上,在NestJS中可以通过以下方式增加一个路由的大小限制:

     app.use('/uploads', json({ limit: '50mb' }));
     app.use(json({ limit: '100kb' }));

需要第二个语句来重置所有其他路由器的限制。


3
你可以使用guard来实现这个功能。
import {
  Injectable,
  CanActivate,
  ExecutionContext,
  applyDecorators,
  UseGuards,
  SetMetadata,
} from '@nestjs/common'
import { Reflector } from '@nestjs/core'

@Injectable()
export class LimitGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest()
    const limit = this.reflector.get<string[]>('limit', context.getHandler())
    return limit > request.socket.bytesRead
  }
}

export const Limit = (limit: number) =>
  applyDecorators(UseGuards(LimitGuard), SetMetadata('limit', limit))

在你的控制器中

  @Limit(1024 * 1024)
  @Post('your-path')
  async limitedMethod(): Promise<string> {
    // ...
  }

1
这是否意味着,例如1GB的数据上传将首先加载到服务器上,然后再由防护程序检查是否超过了限制? - undefined

1

在 main.ts 中设置每个路由的大小限制不如设置所有路由的高限制,然后使用拦截器为每个控制器设置限制。当超过限制时,客户端将获得更详细的错误信息。

import { Injectable, NestInterceptor, ExecutionContext, CallHandler, HttpException } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class SizeLimitInterceptor implements NestInterceptor {
    private sizeLimit = 0;

    constructor(sizeLimit: number) {
        this.sizeLimit = sizeLimit;
    }

    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
        const ctx = context.switchToHttp();
        const request = ctx.getRequest();
        const response = ctx.getResponse();
        const size = request.socket.bytesRead;

        if (size > this.sizeLimit) {
            throw new HttpException('Request Entity Too Large Error', 413);
        }

        return next.handle();
    }
}

您可以在控制器中像这样使用此拦截器:

@UseInterceptors(new SizeLimitInterceptor(1024 * 1024 * 10))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接