From b01b28acd7eae7979568d318c3266b32a40046dd Mon Sep 17 00:00:00 2001 From: koder-ns Date: Fri, 16 Oct 2026 10:33:06 +0100 Subject: [PATCH] added bound --- BackendAcademy/src/app.controller.spec.ts | 51 ++++++++++++++++++++++- BackendAcademy/src/main.ts | 11 ++++- BackendAcademy/tsconfig.json | 3 +- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/BackendAcademy/src/app.controller.spec.ts b/BackendAcademy/src/app.controller.spec.ts index 4f5dfe55e5..4abcb3cdd6 100644 --- a/BackendAcademy/src/app.controller.spec.ts +++ b/BackendAcademy/src/app.controller.spec.ts @@ -1,17 +1,20 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { INestApplication } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; +import { AppModule } from './app.module'; +import request from 'supertest'; describe('AppController', () => { let appController: AppController; beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ + const module: TestingModule = await Test.createTestingModule({ controllers: [AppController], providers: [AppService], }).compile(); - appController = app.get(AppController); + appController = module.get(AppController); }); describe('getHello', () => { @@ -20,3 +23,47 @@ describe('AppController', () => { }); }); }); + +describe('Request body size limit (e2e)', () => { + let app: INestApplication; + + beforeEach(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + await app.init(); + }); + + afterEach(async () => { + await app.close(); + }); + + it('should reject oversized JSON bodies with 413 Payload Too Large', async () => { + // Create a payload larger than the default 1MB limit + const oversizedPayload = { data: 'x'.repeat(2 * 1024 * 1024) }; // 2MB + + const response = await request(app.getHttpServer()) + .post('/api/test') + .send(oversizedPayload) + .expect(413); + + expect(response.body).toHaveProperty('message'); + expect(response.body.message).toContain('payload too large'); + }); + + it('should accept JSON bodies within the size limit', async () => { + // Create a payload well within the 1MB limit + const validPayload = { data: 'x'.repeat(100) }; + + // Note: This endpoint may not exist, but the body size limit + // middleware should still allow the request through (possibly 404) + const response = await request(app.getHttpServer()) + .post('/api/test') + .send(validPayload); + + // Should not be 413 (Payload Too Large) + expect(response.status).not.toBe(413); + }); +}); diff --git a/BackendAcademy/src/main.ts b/BackendAcademy/src/main.ts index 71c0100751..9ca6815dc1 100644 --- a/BackendAcademy/src/main.ts +++ b/BackendAcademy/src/main.ts @@ -4,6 +4,7 @@ import { ConfigService } from '@nestjs/config'; import { NestExpressApplication } from '@nestjs/platform-express'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import helmet from 'helmet'; +import * as express from 'express'; import { AppModule } from './app.module'; // Application entry point: creates the Nest app, applies global @@ -26,6 +27,14 @@ async function bootstrap() { // paths for monitoring tools that expect them un-prefixed). app.setGlobalPrefix('api', { exclude: ['health'] }); + const configService = app.get(ConfigService); + // Enforces a maximum request body size to prevent DoS attacks from + // oversized payloads. Defaults to 1MB; configurable via MAX_BODY_SIZE + // env var (e.g., '5mb', '10mb'). Requests exceeding this limit return + // HTTP 413 (Payload Too Large) with a clear error message. + const maxBodySize = configService.get('MAX_BODY_SIZE', '1mb'); + app.use(express.json({ limit: maxBodySize })); + // Global validation pipe applied to all incoming request bodies/params: // - whitelist: strips properties not defined on the target DTO // - transform: converts payloads into instances of their DTO classes @@ -38,8 +47,6 @@ async function bootstrap() { forbidNonWhitelisted: true, }), ); - - const configService = app.get(ConfigService); // Swagger docs default to enabled unless explicitly turned off via // the SWAGGER_ENABLED env var. const swaggerEnabled = configService.get('SWAGGER_ENABLED', 'true') === 'true'; diff --git a/BackendAcademy/tsconfig.json b/BackendAcademy/tsconfig.json index ab56f093c3..d89e90edf7 100644 --- a/BackendAcademy/tsconfig.json +++ b/BackendAcademy/tsconfig.json @@ -18,7 +18,8 @@ "forceConsistentCasingInFileNames": false, "noFallthroughCasesInSwitch": false, "esModuleInterop": true, - "resolveJsonModule": true + "resolveJsonModule": true, + "ignoreDeprecations": "6.0" }, "include": ["src/**/*", "test/**/*"], "exclude": ["node_modules", "dist"]