Skip to content

Commit

Permalink
add fileSizeLimit
Browse files Browse the repository at this point in the history
  • Loading branch information
talentlessguy committed Oct 2, 2024
1 parent eafa122 commit 7cff78d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const hasBody = (method: string) => ['POST', 'PUT', 'PATCH', 'DELETE'].in

const defaultPayloadLimit = 104857600 // 100KB

export type LimitErrorFn = (payloadLimit: number) => Error
export type LimitErrorFn = (limit: number) => Error

export type ParserOptions = Partial<{
payloadLimit: number
Expand Down Expand Up @@ -91,7 +91,9 @@ const getBoundary = (contentType: string) => {
return match ? `--${match[1]}` : null
}

const parseMultipart = (body: string, boundary: string, { fileCountLimit }: MultipartOptions) => {
const defaultFileSizeLimitErrorFn: LimitErrorFn = (limit) => new Error(`File too large. Limit: ${limit} bytes`)

const parseMultipart = (body: string, boundary: string, { fileCountLimit, fileSizeLimit, fileSizeLimitErrorFn = defaultFileSizeLimitErrorFn }: MultipartOptions) => {
// Split the body into an array of parts
const parts = body.split(new RegExp(`${boundary}(--)?`)).filter((part) => !!part && /content-disposition/i.test(part))
const parsedBody: Record<string, (File | string)[]> = {}
Expand All @@ -104,6 +106,8 @@ const parseMultipart = (body: string, boundary: string, { fileCountLimit }: Mult
const [headers, ...lines] = part.split('\r\n').filter((part) => !!part)
const data = lines.join('\r\n').trim()

if (fileSizeLimit && data.length > fileSizeLimit) throw fileSizeLimitErrorFn(fileSizeLimit)

// Extract the name and filename from the headers
const name = /name="(.+?)"/.exec(headers)![1]
const filename = /filename="(.+?)"/.exec(headers)
Expand All @@ -126,6 +130,7 @@ const parseMultipart = (body: string, boundary: string, { fileCountLimit }: Mult
type MultipartOptions = Partial<{
fileCountLimit: number
fileSizeLimit: number
fileSizeLimitErrorFn: LimitErrorFn
}>

const multipart =
Expand Down
36 changes: 36 additions & 0 deletions test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,3 +459,39 @@ test('should throw multipart if amount of files exceeds limit', async () => {
method: 'POST',
}).expect(413, 'Too many files. Limit: 1')
})

test('should throw multipart if exceeds allowed file size', async () => {
const server = createServer(async (req: ReqWithBody, res) => {
await multipart({ fileSizeLimit: 10 })(req, res, (err) => {
if (err) res.writeHead(413).end(err.message)
else res.end(req.body)
})
})

const fd = new FormData()

fd.set('file', new File(['hello world'], 'hello.txt', { type: 'text/plain' }))

await makeFetch(server)('/', {
body: fd,
method: 'POST',
}).expect(413, 'File too large. Limit: 10 bytes')
})

test('should throw multipart if exceeds allowed file size with a custom error', async () => {
const server = createServer(async (req: ReqWithBody, res) => {
await multipart({ fileSizeLimit: 10, fileSizeLimitErrorFn: (limit) => new Error(`File too large. Limit: ${limit / 1024}KB`) })(req, res, (err) => {
if (err) res.writeHead(413).end(err.message)
else res.end(req.body)
})
})

const fd = new FormData()

fd.set('file', new File(['hello world'], 'hello.txt', { type: 'text/plain' }))

await makeFetch(server)('/', {
body: fd,
method: 'POST',
}).expect(413, 'File too large. Limit: 0.009765625KB')
})

0 comments on commit 7cff78d

Please sign in to comment.