/** @jest-environment node */ import { readFile } from 'fs/promises' import path from 'path' const guardedRoutes = [ 'app/api/upload/s3-original/route.ts', 'app/api/upload/s3/route.ts', 'app/api/upload/preview/route.ts', 'app/api/materials/[id]/skus/upload/route.ts', 'app/api/user/avatar/route.ts', 'app/api/materials/[id]/route.ts', 'app/api/materials/update/route.ts', 'app/api/system-settings/upload-logo/route.ts', ] as const const preBoundedLegacyRoutes = [ 'app/api/upload/psd/route.ts', 'app/api/materials/[id]/white-background/route.ts', 'app/api/external/standard-model-white-background/by-barcode/route.ts', 'app/api/external/standard-model-white-background/by-spu/route.ts', ] as const describe('multipart routes are bounded before parsing', () => { test.each(guardedRoutes)('%s checks headers and acquires a slot before formData', async (routePath) => { const source = await readFile(path.join(process.cwd(), routePath), 'utf8') const headerGuard = source.indexOf('assertBoundedMultipartHeaders(') const acquireSlot = source.indexOf('boundedMultipartRequestLimiter.acquire()') const parseBody = source.indexOf('request.formData()') const parsedFiles = source.indexOf('assertMultipartFiles(', parseBody) expect(headerGuard).toBeGreaterThan(0) expect(acquireSlot).toBeGreaterThan(headerGuard) expect(parseBody).toBeGreaterThan(acquireSlot) expect(parsedFiles).toBeGreaterThan(parseBody) expect(source).toContain('releaseRequestSlot?.()') }) test.each(preBoundedLegacyRoutes)('%s acquires a slot after its existing size check', async (routePath) => { const source = await readFile(path.join(process.cwd(), routePath), 'utf8') const headerGuard = source.indexOf("headers.get('content-length')") const acquireSlot = source.indexOf('boundedMultipartRequestLimiter.acquire()') const parseBody = source.indexOf('request.formData()') expect(headerGuard).toBeGreaterThan(0) expect(acquireSlot).toBeGreaterThan(headerGuard) expect(parseBody).toBeGreaterThan(acquireSlot) expect(source).toContain('releaseRequestSlot?.()') }) test('stable proxy uses a small fallback and explicit upload route ceilings', async () => { const source = (await readFile( path.join(process.cwd(), 'scripts/git-incremental-deploy.ps1'), 'utf8', )).replace(/\r\n/g, '\n') expect(source).toContain('client_max_body_size 16m;') expect(source).not.toContain('client_max_body_size 1000m;') const requiredFragments = [ 'location = /api/upload/preview {\n client_max_body_size 53m;', 'location ~ "^/api/upload/s3(?:-original)?\\$" {\n client_max_body_size 103m;', 'location = /api/materials/update {\n client_max_body_size 11m;', 'location ~ "^/api/(?:user/avatar|system-settings/upload-logo)\\$" {\n client_max_body_size 7m;', '/skus/upload)\\$" {\n client_max_body_size 131m;', '/white-background|api/external/standard-model-white-background/(?:by-spu|by-barcode))\\$" {\n client_max_body_size 106m;', ] for (const fragment of requiredFragments) { expect(source).toContain(fragment) } const boundedLocations = source.match(/client_max_body_size (?:7|11|53|103|106|131)m;[\s\S]{0,180}?proxy_request_buffering off;/g) || [] expect(boundedLocations.length).toBeGreaterThanOrEqual(7) }) })