From 092ae3392268412ea57ce26760c3ecdd1f62725c Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Wed, 24 Jan 2024 08:22:56 +0000 Subject: [PATCH 01/14] feat: new built-in middleware --- deno_dist/middleware/body-parser/index.ts | 89 +++++++ src/middleware/body-parser/index.test.ts | 283 ++++++++++++++++++++++ src/middleware/body-parser/index.ts | 89 +++++++ 3 files changed, 461 insertions(+) create mode 100644 deno_dist/middleware/body-parser/index.ts create mode 100644 src/middleware/body-parser/index.test.ts create mode 100644 src/middleware/body-parser/index.ts diff --git a/deno_dist/middleware/body-parser/index.ts b/deno_dist/middleware/body-parser/index.ts new file mode 100644 index 000000000..22dd8ba68 --- /dev/null +++ b/deno_dist/middleware/body-parser/index.ts @@ -0,0 +1,89 @@ +import { Context, MiddlewareHandler } from '../../index.ts' + +type bodyParserOptions = { + type?: 'body' | 'json' | 'form' | 'text' + limit?: number + handler?: (c: Context) => Response, + onError?: (c: Context) => Response +} + +const defaultOptions: bodyParserOptions = { + type: 'body', + limit: 2147483647, + handler: (c: Context) => { + return c.text('413 Request Entity Too Large', 413) + }, + onError: (c: Context) => { + return c.text("Internal Server Error", 500) + } +} + +const allowMethods = ['POST', 'PUT', 'PATCH'] + +export const bodyParser = ( + options: bodyParserOptions = defaultOptions +): MiddlewareHandler<{ + Variables: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + body: () => T + } +}> => { + const parseOptions: bodyParserOptions = { + ...defaultOptions, + ...options, + } + + return async function bodyParse(c: Context, next: () => Promise) { + if ( + allowMethods.includes(c.req.method.toUpperCase()) && + parseOptions.handler && + parseOptions.limit && + parseOptions.type + ) { + const req = c.req.raw.clone() + const blob = await req.blob() + const bodySize = blob.size + + if (bodySize >= parseOptions.limit) { + c.res = parseOptions.handler(c) + c.finalized = true + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let parsedData: any = blob + + switch (parseOptions.type) { + case 'body': + parsedData = blob + break + case 'text': + parsedData = await blob.text() + break + case 'json': + parsedData = JSON.parse(await blob.text()) + break + case 'form': + parsedData = await c.req.formData() + break + default: + parsedData = await blob.text() + break + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + c.set('body', () => parsedData as T) + } + + await next() + } +} + +/** + * Uint any + * @example + * ```ts + * const limit = 100 * Uint.kb // 100kb + * const limit2 = 1 * Unit.gb // 1gb + * ``` + */ +export const Uint = { b: 1, kb: 1000, mb: 1000 ** 2, gb: 1000 ** 3, tb: 1000 ** 4, pb: 1000 ** 5 } diff --git a/src/middleware/body-parser/index.test.ts b/src/middleware/body-parser/index.test.ts new file mode 100644 index 000000000..485e2b249 --- /dev/null +++ b/src/middleware/body-parser/index.test.ts @@ -0,0 +1,283 @@ +import { Hono } from '../../hono' +import { Uint, bodyParser } from '.' + +describe('bodyParse works', () => { + const app = new Hono() + + app.post( + '/max-64mb/body', + bodyParser({ + type: 'body', + limit: 64 * Uint.mb, + }), + (c) => { + return c.json({ + size: c.var.body().size, + type: c.var.body().type, + }) + } + ) + + it('Should return same body on POST', async () => { + const data = { + hono: 'is', + } + const res = await app.request( + new Request('https://localhost/max-64mb/body', { + method: 'POST', + body: JSON.stringify(data), + }) + ) + + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.json()).toEqual({ + size: 13, + type: 'text/plain;charset=utf-8', + }) + }) + + app.post( + '/max-64mb/json', + bodyParser({ + type: 'json', + limit: 64 * Uint.mb, + }), + (c) => { + return c.json(c.var.body()) + } + ) + + it('Should return same json on POST', async () => { + const data = { + hono: 'is', + } + const res = await app.request( + new Request('https://localhost/max-64mb/json', { + method: 'POST', + body: JSON.stringify(data), + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.json()).toEqual(data) + }) + + + app.post( + '/max-64mb/json-error', + bodyParser({ + type: 'json', + limit: 64 * Uint.mb, + }), + (c) => { + return c.json(c.var.body()) + } + ) + + it('Should return json-error on POST', async () => { + const data = `{ + hono: 'is', + }cool` + + const res = await app.request( + new Request('https://localhost/max-64mb/json-error', { + method: 'POST', + body: data, + }) + ) + + expect(res).not.toBeNull() + expect(res.status).toBe(500) + expect(await res.text()).toBe("Internal Server Error") + }) + + + app.post( + '/max-64mb/text', + bodyParser({ + type: 'text', + limit: 64 * Uint.mb, + }), + (c) => { + return c.text(c.var.body()) + } + ) + + it('Should return same text on POST', async () => { + const data = 'hono is cool' + const res = await app.request( + new Request('https://localhost/max-64mb/text', { + method: 'POST', + body: data, + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('hono is cool') + }) + + app.post( + '/max-64mb/form', + bodyParser({ + type: 'form', + limit: 64 * Uint.mb, + }), + (c) => { + return c.text(c.var.body().toString()) + } + ) + + it('Should return same formData on POST', async () => { + const data = new FormData() + const res = await app.request( + new Request('https://localhost/max-64mb/form', { + method: 'POST', + body: data, + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('[object FormData]') + }) + + app.use( + '/max-32bit/*', + bodyParser({ + type: 'body', + }) + ) + + app.all('/max-32bit', (c) => c.text('hono is cool')) + + it('Should return hono is cool on GET', async () => { + const res = await app.request( + new Request('https://localhost/max-32bit', { + method: 'POST', + body: JSON.stringify({ + hono: 'is', + }), + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('hono is cool') + }) + + it('Should return hono is cool on POST', async () => { + const res = await app.request( + new Request('https://localhost/max-32bit', { + method: 'POST', + body: JSON.stringify({ + hono: 'is', + }), + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('hono is cool') + }) + + it('Should return hono is cool on PUT', async () => { + const res = await app.request( + new Request('https://localhost/max-32bit', { + method: 'PUT', + body: JSON.stringify({ + hono: 'is', + }), + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('hono is cool') + }) + + it('Should return hono is cool on PATCH', async () => { + const res = await app.request( + new Request('https://localhost/max-32bit', { + method: 'PATCH', + body: JSON.stringify({ + hono: 'is', + }), + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('hono is cool') + }) + + app.use( + '/max-8byte', + bodyParser({ + type: 'text', + limit: 8 * Uint.b, + }) + ) + + app.post('/max-8byte', (c) => c.text('hono is cool')) + + it('Should return 413 Request Entity Too Large on POST', async () => { + const res = await app.request( + new Request('https://localhost/max-8byte', { + method: 'POST', + body: JSON.stringify({ + hono: 'is', + }), + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('413 Request Entity Too Large') + }) + + it('Should return hono is cool on POST', async () => { + const res = await app.request( + new Request('https://localhost/max-8byte', { + method: 'POST', + body: 'hono', + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('hono is cool') + }) + + app.use( + '/max-8byte-custom', + bodyParser({ + type: 'text', + limit: 8 * Uint.b, + handler: (c) => { + return c.text('not cool', 413) + }, + }) + ) + + app.post('/max-8byte-custom', (c) => c.text('hono is cool')) + + it('Should return not cool with 413 on POST', async () => { + const res = await app.request( + new Request('https://localhost/max-8byte-custom', { + method: 'POST', + body: JSON.stringify({ + hono: 'is', + }), + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('not cool') + }) + + it('Should return hono is cool on POST', async () => { + const res = await app.request( + new Request('https://localhost/max-8byte-custom', { + method: 'POST', + body: 'hono', + }) + ) + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('hono is cool') + }) +}) diff --git a/src/middleware/body-parser/index.ts b/src/middleware/body-parser/index.ts new file mode 100644 index 000000000..9b029577b --- /dev/null +++ b/src/middleware/body-parser/index.ts @@ -0,0 +1,89 @@ +import { Context, MiddlewareHandler } from '../..' + +type bodyParserOptions = { + type?: 'body' | 'json' | 'form' | 'text' + limit?: number + handler?: (c: Context) => Response, + onError?: (c: Context) => Response +} + +const defaultOptions: bodyParserOptions = { + type: 'body', + limit: 2147483647, + handler: (c: Context) => { + return c.text('413 Request Entity Too Large', 413) + }, + onError: (c: Context) => { + return c.text("Internal Server Error", 500) + } +} + +const allowMethods = ['POST', 'PUT', 'PATCH'] + +export const bodyParser = ( + options: bodyParserOptions = defaultOptions +): MiddlewareHandler<{ + Variables: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + body: () => T + } +}> => { + const parseOptions: bodyParserOptions = { + ...defaultOptions, + ...options, + } + + return async function bodyParse(c: Context, next: () => Promise) { + if ( + allowMethods.includes(c.req.method.toUpperCase()) && + parseOptions.handler && + parseOptions.limit && + parseOptions.type + ) { + const req = c.req.raw.clone() + const blob = await req.blob() + const bodySize = blob.size + + if (bodySize >= parseOptions.limit) { + c.res = parseOptions.handler(c) + c.finalized = true + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let parsedData: any = blob + + switch (parseOptions.type) { + case 'body': + parsedData = blob + break + case 'text': + parsedData = await blob.text() + break + case 'json': + parsedData = JSON.parse(await blob.text()) + break + case 'form': + parsedData = await c.req.formData() + break + default: + parsedData = await blob.text() + break + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + c.set('body', () => parsedData as T) + } + + await next() + } +} + +/** + * Uint any + * @example + * ```ts + * const limit = 100 * Uint.kb // 100kb + * const limit2 = 1 * Unit.gb // 1gb + * ``` + */ +export const Uint = { b: 1, kb: 1000, mb: 1000 ** 2, gb: 1000 ** 3, tb: 1000 ** 4, pb: 1000 ** 5 } From 4aee910888de516d2b0e8ff824ae443cd8f3d17c Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Wed, 24 Jan 2024 08:25:35 +0000 Subject: [PATCH 02/14] chore: format --- src/middleware/body-parser/index.test.ts | 20 +++++++++----------- src/middleware/body-parser/index.ts | 6 +++--- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/middleware/body-parser/index.test.ts b/src/middleware/body-parser/index.test.ts index 485e2b249..e22061b7d 100644 --- a/src/middleware/body-parser/index.test.ts +++ b/src/middleware/body-parser/index.test.ts @@ -63,7 +63,6 @@ describe('bodyParse works', () => { expect(await res.json()).toEqual(data) }) - app.post( '/max-64mb/json-error', bodyParser({ @@ -80,19 +79,18 @@ describe('bodyParse works', () => { hono: 'is', }cool` - const res = await app.request( - new Request('https://localhost/max-64mb/json-error', { - method: 'POST', - body: data, - }) - ) + const res = await app.request( + new Request('https://localhost/max-64mb/json-error', { + method: 'POST', + body: data, + }) + ) - expect(res).not.toBeNull() - expect(res.status).toBe(500) - expect(await res.text()).toBe("Internal Server Error") + expect(res).not.toBeNull() + expect(res.status).toBe(500) + expect(await res.text()).toBe('Internal Server Error') }) - app.post( '/max-64mb/text', bodyParser({ diff --git a/src/middleware/body-parser/index.ts b/src/middleware/body-parser/index.ts index 9b029577b..65da566d0 100644 --- a/src/middleware/body-parser/index.ts +++ b/src/middleware/body-parser/index.ts @@ -3,7 +3,7 @@ import { Context, MiddlewareHandler } from '../..' type bodyParserOptions = { type?: 'body' | 'json' | 'form' | 'text' limit?: number - handler?: (c: Context) => Response, + handler?: (c: Context) => Response onError?: (c: Context) => Response } @@ -14,8 +14,8 @@ const defaultOptions: bodyParserOptions = { return c.text('413 Request Entity Too Large', 413) }, onError: (c: Context) => { - return c.text("Internal Server Error", 500) - } + return c.text('Internal Server Error', 500) + }, } const allowMethods = ['POST', 'PUT', 'PATCH'] From 49086ba59ea5981e7609c6eaabb1789d0e9c2d9b Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Wed, 24 Jan 2024 08:28:01 +0000 Subject: [PATCH 03/14] chore: lint:fix & denoify --- deno_dist/middleware/body-parser/index.ts | 8 ++++---- src/middleware/body-parser/index.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/deno_dist/middleware/body-parser/index.ts b/deno_dist/middleware/body-parser/index.ts index 22dd8ba68..b7a1ae989 100644 --- a/deno_dist/middleware/body-parser/index.ts +++ b/deno_dist/middleware/body-parser/index.ts @@ -1,9 +1,9 @@ -import { Context, MiddlewareHandler } from '../../index.ts' +import type { Context, MiddlewareHandler } from '../../index.ts' type bodyParserOptions = { type?: 'body' | 'json' | 'form' | 'text' limit?: number - handler?: (c: Context) => Response, + handler?: (c: Context) => Response onError?: (c: Context) => Response } @@ -14,8 +14,8 @@ const defaultOptions: bodyParserOptions = { return c.text('413 Request Entity Too Large', 413) }, onError: (c: Context) => { - return c.text("Internal Server Error", 500) - } + return c.text('Internal Server Error', 500) + }, } const allowMethods = ['POST', 'PUT', 'PATCH'] diff --git a/src/middleware/body-parser/index.ts b/src/middleware/body-parser/index.ts index 65da566d0..3c4b85787 100644 --- a/src/middleware/body-parser/index.ts +++ b/src/middleware/body-parser/index.ts @@ -1,4 +1,4 @@ -import { Context, MiddlewareHandler } from '../..' +import type { Context, MiddlewareHandler } from '../..' type bodyParserOptions = { type?: 'body' | 'json' | 'form' | 'text' From e5afb9bca1124610adf52e34b384683e0301fb86 Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Wed, 24 Jan 2024 10:06:49 +0000 Subject: [PATCH 04/14] refactor,fix --- deno_dist/middleware/body-parser/index.ts | 11 +++-------- src/middleware/body-parser/index.ts | 11 +++-------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/deno_dist/middleware/body-parser/index.ts b/deno_dist/middleware/body-parser/index.ts index b7a1ae989..40803a3d0 100644 --- a/deno_dist/middleware/body-parser/index.ts +++ b/deno_dist/middleware/body-parser/index.ts @@ -4,18 +4,14 @@ type bodyParserOptions = { type?: 'body' | 'json' | 'form' | 'text' limit?: number handler?: (c: Context) => Response - onError?: (c: Context) => Response } const defaultOptions: bodyParserOptions = { type: 'body', - limit: 2147483647, + limit: 0, handler: (c: Context) => { return c.text('413 Request Entity Too Large', 413) }, - onError: (c: Context) => { - return c.text('Internal Server Error', 500) - }, } const allowMethods = ['POST', 'PUT', 'PATCH'] @@ -44,9 +40,8 @@ export const bodyParser = ( const blob = await req.blob() const bodySize = blob.size - if (bodySize >= parseOptions.limit) { - c.res = parseOptions.handler(c) - c.finalized = true + if (parseOptions.limit !== 0 && bodySize >= parseOptions.limit) { + return parseOptions.handler(c) } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/middleware/body-parser/index.ts b/src/middleware/body-parser/index.ts index 3c4b85787..c5b6d601e 100644 --- a/src/middleware/body-parser/index.ts +++ b/src/middleware/body-parser/index.ts @@ -4,18 +4,14 @@ type bodyParserOptions = { type?: 'body' | 'json' | 'form' | 'text' limit?: number handler?: (c: Context) => Response - onError?: (c: Context) => Response } const defaultOptions: bodyParserOptions = { type: 'body', - limit: 2147483647, + limit: 0, handler: (c: Context) => { return c.text('413 Request Entity Too Large', 413) }, - onError: (c: Context) => { - return c.text('Internal Server Error', 500) - }, } const allowMethods = ['POST', 'PUT', 'PATCH'] @@ -44,9 +40,8 @@ export const bodyParser = ( const blob = await req.blob() const bodySize = blob.size - if (bodySize >= parseOptions.limit) { - c.res = parseOptions.handler(c) - c.finalized = true + if (parseOptions.limit !== 0 && bodySize >= parseOptions.limit) { + return parseOptions.handler(c) } // eslint-disable-next-line @typescript-eslint/no-explicit-any From 07a805693e5be712f02e3e78e757c07d9bfe1f20 Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Fri, 26 Jan 2024 03:20:59 +0000 Subject: [PATCH 05/14] fix: to bodyLimit --- src/middleware/body-limit/index.test.ts | 280 ++++++++++++++++++++++ src/middleware/body-limit/index.ts | 131 +++++++++++ src/middleware/body-parser/index.test.ts | 281 ----------------------- src/middleware/body-parser/index.ts | 84 ------- 4 files changed, 411 insertions(+), 365 deletions(-) create mode 100644 src/middleware/body-limit/index.test.ts create mode 100644 src/middleware/body-limit/index.ts delete mode 100644 src/middleware/body-parser/index.test.ts delete mode 100644 src/middleware/body-parser/index.ts diff --git a/src/middleware/body-limit/index.test.ts b/src/middleware/body-limit/index.test.ts new file mode 100644 index 000000000..bfa96dd04 --- /dev/null +++ b/src/middleware/body-limit/index.test.ts @@ -0,0 +1,280 @@ +import { Hono } from '../../hono' +import { Uint, bodyLimit } from '.' + +describe('bodyLimit by Middleware', () => { + const app = new Hono() + + const exampleBody = 'hono is cool' // 12byte + const exampleText = 'hono is cool' // 12byte + const exampleText2 = 'hono is cool and cute' // 21byte + const exampleJSON = { + hono: 'is cool and fast', + } // 27byte + const exampleJSON2 = { + hono: 'is cool and fast', + cool: 'is hono', + } // 44byte + const exampleForm = new FormData() + exampleForm.append('hono', 'is cool') + // 100 byte to 200 byte + const exampleForm2 = new FormData() + exampleForm2.append('hono', 'is cool') + exampleForm2.append('hono', 'is cute') + exampleForm2.append('hono', 'is fast') + // 300 byte to 400 byte + + app.post( + '/body-limit-15byte', + bodyLimit({ + limit: 15 * Uint.b, + }), + (c) => { + return c.text('yes') + } + ) + + it('body limit pass tests', async () => { + const res = await app.request('/body-limit-15byte', { + method: 'POST', + body: exampleText, + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('yes') + }) + + it('body limit fail tests', async () => { + const res = await app.request('/body-limit-15byte', { + method: 'POST', + body: exampleText2, + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('413 Request Entity Too Large') + }) + + app.post( + '/text-limit-15byte', + bodyLimit({ + type: 'text', + limit: 15 * Uint.b, + }), + (c) => { + return c.text('yes') + } + ) + + it('text limit pass tests', async () => { + const res = await app.request('/text-limit-15byte', { + method: 'POST', + body: exampleText, + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('yes') + }) + + it('text limit fail tests', async () => { + const res = await app.request('/text-limit-15byte', { + method: 'POST', + body: exampleText2, + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('413 Request Entity Too Large') + }) + + app.post( + '/json-limit-35byte', + bodyLimit({ + type: 'json', + limit: 35 * Uint.b, + }), + (c) => { + return c.text('yes') + } + ) + + it('json limit pass tests', async () => { + const res = await app.request('/json-limit-35byte', { + method: 'POST', + headers: new Headers({ + 'Content-Type': 'application/json, text/plain', + }), + body: JSON.stringify(exampleJSON), + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('yes') + }) + + it('json limit fail tests with empty', async () => { + const res = await app.request('/json-limit-35byte', { + method: 'POST', + headers: new Headers({ + 'Content-Type': ' ' + 'application/json, text/plain', + }), + body: JSON.stringify(exampleJSON2), + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('413 Request Entity Too Large') + }) + + app.post( + '/form-limit-300byte', + bodyLimit({ + type: 'form', + limit: 300 * Uint.b, + }), + (c) => { + return c.text('yes') + } + ) + + it('form limit pass tests', async () => { + const res = await app.request('/form-limit-300byte', { + method: 'POST', + headers: new Headers({ + 'Content-Type': 'application/x-www-form-urlencoded', + }), + body: exampleForm, + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('yes') + }) + + it('form limit fail tests', async () => { + const res = await app.request('/form-limit-300byte', { + method: 'POST', + headers: new Headers({ + 'Content-Type': 'application/x-www-form-urlencoded', + }), + body: exampleForm2, + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('413 Request Entity Too Large') + }) + + app.post( + '/text-limit-15byte-custom', + bodyLimit({ + type: 'text', + limit: 15 * Uint.b, + handler: (c) => { + return c.text('no', 413) + }, + }), + (c) => { + return c.text('yes') + } + ) + + it('text limit with custom handler', async () => { + const res = await app.request('/text-limit-15byte-custom', { + method: 'POST', + body: exampleText2, + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('no') + }) + + app.post( + '/json-limit-35byte-custom', + bodyLimit({ + type: 'json', + limit: 35 * Uint.b, + handler: (c) => { + return c.text('no', 413) + }, + }), + (c) => { + return c.text('yes') + } + ) + + it('json limit with custom handler with lower case', async () => { + const res = await app.request('/json-limit-35byte-custom', { + method: 'POST', + headers: new Headers({ + 'content-type': 'application/json, text/plain', + }), + body: JSON.stringify(exampleJSON2), + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('no') + }) + + app.post( + '/enum-limit-custom', + bodyLimit([ + { + type: 'json', + limit: 35 * Uint.b, + handler: (c) => { + return c.text('no', 413) + }, + }, + { + type: 'text', + limit: 35 * Uint.b, + handler: (c) => { + return c.text('no', 413) + }, + }, + ]), + (c) => { + return c.text('yes') + } + ) + + it('enum limit pass tests', async () => { + const res = await app.request('/enum-limit-custom', { + method: 'POST', + body: exampleText, + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(200) + expect(await res.text()).toBe('yes') + }) + + it('enum limit with custom handler with lower case', async () => { + const res = await app.request('/enum-limit-custom', { + method: 'POST', + headers: new Headers({ + 'content-type': 'application/json, text/plain', + }), + body: JSON.stringify(exampleJSON2), + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('no') + }) + + it('Uint test', () => { + let beforeSize = 1 / 1000 + + for (let i = 0, keys = Object.keys(Uint), len = keys.length; i < len; i++) { + // @ts-expect-error: + const size = Uint[keys[i]] + expect(size === beforeSize * 1000).toBeTruthy() + beforeSize = size + } + }) +}) diff --git a/src/middleware/body-limit/index.ts b/src/middleware/body-limit/index.ts new file mode 100644 index 000000000..173ae9a76 --- /dev/null +++ b/src/middleware/body-limit/index.ts @@ -0,0 +1,131 @@ +import type { Context, MiddlewareHandler } from '../..' + +const bodyTypes = ['body', 'json', 'form', 'text'] as const + +type bodyLimitOptions = { + type?: typeof bodyTypes[number] + limit?: number + handler?: (c: Context) => Response +}[] + +type bodyLimitObject = { + body?: bodyLimitOptions[number] + json?: bodyLimitOptions[number] + form?: bodyLimitOptions[number] + text?: bodyLimitOptions[number] +} + +const defaultOptions: bodyLimitOptions = bodyTypes.map((bodyType) => { + return { + type: bodyType, + limit: NaN, + handler: (c: Context) => { + return c.text('413 Request Entity Too Large', 413) + }, + } +}) + +const allowMethods = ['POST', 'PUT', 'PATCH'] + +const deleteSameType = (options: bodyLimitOptions): bodyLimitObject => { + const objects: bodyLimitObject = {} + + for (let i = 0, len = options.length; i < len; i++) { + const option = options[i] + objects[option.type ?? 'body'] = { + type: 'body', + limit: NaN, + handler: (c: Context) => { + return c.text('413 Request Entity Too Large', 413) + }, + ...option, + } + } + + return objects +} + +/** + * Built-in Middleware for limit body size + * + * @example + * ```ts + * app.post( + * '/hello', + * bodyLimit({ + * type: 'text', // body | json | form | text + * limit: 15 * Uint.b, // byte, + * handler: (c) => { + * return c.text("oveflow :("); + * } + * }), + * (c) => { + * return c.text('pass :)') + * } + * ) + * + * /** + * body: all type + * text: taxt/plain + * json: application/json + * form: application/x-www-form-urlencoded + * *\/ + * ``` + */ +export const bodyLimit = ( + options: bodyLimitOptions | bodyLimitOptions[number] = defaultOptions +): MiddlewareHandler => { + const limitOptions: bodyLimitObject = deleteSameType([...defaultOptions, ...[options].flat()]) + + return async function bodylimit(c: Context, next: () => Promise) { + if (allowMethods.includes(c.req.method.toUpperCase())) { + const req = c.req.raw.clone() + const blob = await req.blob() + const bodySize = blob.size + + let type: typeof bodyTypes[number] = 'body' + const ContentType = req.headers.get('Content-Type')?.trim() ?? '' + + if (ContentType.startsWith('text/plain')) { + type = 'text' + } else if (ContentType.startsWith('application/json')) { + type = 'json' + } else if (ContentType.startsWith('application/x-www-form-urlencoded')) { + type = 'form' + } + + const limitOption = limitOptions[type] + const bodyLimitOption = limitOptions['body'] + + if ( + limitOption && + limitOption.limit && + limitOption.handler && + !isNaN(limitOption.limit) && + bodySize > limitOption.limit + ) { + return limitOption.handler(c) + } else if ( + bodyLimitOption && + bodyLimitOption.limit && + bodyLimitOption.handler && + !isNaN(bodyLimitOption.limit) && + bodySize > bodyLimitOption.limit + ) { + return bodyLimitOption.handler(c) + } + } + + await next() + } +} + +/** + * Uint any + * @example + * ```ts + * const limit = 100 * Uint.kb // 100kb + * const limit2 = 1 * Unit.gb // 1gb + * ``` + */ +export const Uint = { b: 1, kb: 1000, mb: 1000 ** 2, gb: 1000 ** 3, tb: 1000 ** 4, pb: 1000 ** 5 } diff --git a/src/middleware/body-parser/index.test.ts b/src/middleware/body-parser/index.test.ts deleted file mode 100644 index e22061b7d..000000000 --- a/src/middleware/body-parser/index.test.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { Hono } from '../../hono' -import { Uint, bodyParser } from '.' - -describe('bodyParse works', () => { - const app = new Hono() - - app.post( - '/max-64mb/body', - bodyParser({ - type: 'body', - limit: 64 * Uint.mb, - }), - (c) => { - return c.json({ - size: c.var.body().size, - type: c.var.body().type, - }) - } - ) - - it('Should return same body on POST', async () => { - const data = { - hono: 'is', - } - const res = await app.request( - new Request('https://localhost/max-64mb/body', { - method: 'POST', - body: JSON.stringify(data), - }) - ) - - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.json()).toEqual({ - size: 13, - type: 'text/plain;charset=utf-8', - }) - }) - - app.post( - '/max-64mb/json', - bodyParser({ - type: 'json', - limit: 64 * Uint.mb, - }), - (c) => { - return c.json(c.var.body()) - } - ) - - it('Should return same json on POST', async () => { - const data = { - hono: 'is', - } - const res = await app.request( - new Request('https://localhost/max-64mb/json', { - method: 'POST', - body: JSON.stringify(data), - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.json()).toEqual(data) - }) - - app.post( - '/max-64mb/json-error', - bodyParser({ - type: 'json', - limit: 64 * Uint.mb, - }), - (c) => { - return c.json(c.var.body()) - } - ) - - it('Should return json-error on POST', async () => { - const data = `{ - hono: 'is', - }cool` - - const res = await app.request( - new Request('https://localhost/max-64mb/json-error', { - method: 'POST', - body: data, - }) - ) - - expect(res).not.toBeNull() - expect(res.status).toBe(500) - expect(await res.text()).toBe('Internal Server Error') - }) - - app.post( - '/max-64mb/text', - bodyParser({ - type: 'text', - limit: 64 * Uint.mb, - }), - (c) => { - return c.text(c.var.body()) - } - ) - - it('Should return same text on POST', async () => { - const data = 'hono is cool' - const res = await app.request( - new Request('https://localhost/max-64mb/text', { - method: 'POST', - body: data, - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.text()).toBe('hono is cool') - }) - - app.post( - '/max-64mb/form', - bodyParser({ - type: 'form', - limit: 64 * Uint.mb, - }), - (c) => { - return c.text(c.var.body().toString()) - } - ) - - it('Should return same formData on POST', async () => { - const data = new FormData() - const res = await app.request( - new Request('https://localhost/max-64mb/form', { - method: 'POST', - body: data, - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.text()).toBe('[object FormData]') - }) - - app.use( - '/max-32bit/*', - bodyParser({ - type: 'body', - }) - ) - - app.all('/max-32bit', (c) => c.text('hono is cool')) - - it('Should return hono is cool on GET', async () => { - const res = await app.request( - new Request('https://localhost/max-32bit', { - method: 'POST', - body: JSON.stringify({ - hono: 'is', - }), - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.text()).toBe('hono is cool') - }) - - it('Should return hono is cool on POST', async () => { - const res = await app.request( - new Request('https://localhost/max-32bit', { - method: 'POST', - body: JSON.stringify({ - hono: 'is', - }), - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.text()).toBe('hono is cool') - }) - - it('Should return hono is cool on PUT', async () => { - const res = await app.request( - new Request('https://localhost/max-32bit', { - method: 'PUT', - body: JSON.stringify({ - hono: 'is', - }), - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.text()).toBe('hono is cool') - }) - - it('Should return hono is cool on PATCH', async () => { - const res = await app.request( - new Request('https://localhost/max-32bit', { - method: 'PATCH', - body: JSON.stringify({ - hono: 'is', - }), - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.text()).toBe('hono is cool') - }) - - app.use( - '/max-8byte', - bodyParser({ - type: 'text', - limit: 8 * Uint.b, - }) - ) - - app.post('/max-8byte', (c) => c.text('hono is cool')) - - it('Should return 413 Request Entity Too Large on POST', async () => { - const res = await app.request( - new Request('https://localhost/max-8byte', { - method: 'POST', - body: JSON.stringify({ - hono: 'is', - }), - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(413) - expect(await res.text()).toBe('413 Request Entity Too Large') - }) - - it('Should return hono is cool on POST', async () => { - const res = await app.request( - new Request('https://localhost/max-8byte', { - method: 'POST', - body: 'hono', - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.text()).toBe('hono is cool') - }) - - app.use( - '/max-8byte-custom', - bodyParser({ - type: 'text', - limit: 8 * Uint.b, - handler: (c) => { - return c.text('not cool', 413) - }, - }) - ) - - app.post('/max-8byte-custom', (c) => c.text('hono is cool')) - - it('Should return not cool with 413 on POST', async () => { - const res = await app.request( - new Request('https://localhost/max-8byte-custom', { - method: 'POST', - body: JSON.stringify({ - hono: 'is', - }), - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(413) - expect(await res.text()).toBe('not cool') - }) - - it('Should return hono is cool on POST', async () => { - const res = await app.request( - new Request('https://localhost/max-8byte-custom', { - method: 'POST', - body: 'hono', - }) - ) - expect(res).not.toBeNull() - expect(res.status).toBe(200) - expect(await res.text()).toBe('hono is cool') - }) -}) diff --git a/src/middleware/body-parser/index.ts b/src/middleware/body-parser/index.ts deleted file mode 100644 index c5b6d601e..000000000 --- a/src/middleware/body-parser/index.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { Context, MiddlewareHandler } from '../..' - -type bodyParserOptions = { - type?: 'body' | 'json' | 'form' | 'text' - limit?: number - handler?: (c: Context) => Response -} - -const defaultOptions: bodyParserOptions = { - type: 'body', - limit: 0, - handler: (c: Context) => { - return c.text('413 Request Entity Too Large', 413) - }, -} - -const allowMethods = ['POST', 'PUT', 'PATCH'] - -export const bodyParser = ( - options: bodyParserOptions = defaultOptions -): MiddlewareHandler<{ - Variables: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - body: () => T - } -}> => { - const parseOptions: bodyParserOptions = { - ...defaultOptions, - ...options, - } - - return async function bodyParse(c: Context, next: () => Promise) { - if ( - allowMethods.includes(c.req.method.toUpperCase()) && - parseOptions.handler && - parseOptions.limit && - parseOptions.type - ) { - const req = c.req.raw.clone() - const blob = await req.blob() - const bodySize = blob.size - - if (parseOptions.limit !== 0 && bodySize >= parseOptions.limit) { - return parseOptions.handler(c) - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let parsedData: any = blob - - switch (parseOptions.type) { - case 'body': - parsedData = blob - break - case 'text': - parsedData = await blob.text() - break - case 'json': - parsedData = JSON.parse(await blob.text()) - break - case 'form': - parsedData = await c.req.formData() - break - default: - parsedData = await blob.text() - break - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - c.set('body', () => parsedData as T) - } - - await next() - } -} - -/** - * Uint any - * @example - * ```ts - * const limit = 100 * Uint.kb // 100kb - * const limit2 = 1 * Unit.gb // 1gb - * ``` - */ -export const Uint = { b: 1, kb: 1000, mb: 1000 ** 2, gb: 1000 ** 3, tb: 1000 ** 4, pb: 1000 ** 5 } From b59b4256026a4a6f38f1f504bd59dac2aad13e6c Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Fri, 26 Jan 2024 03:21:53 +0000 Subject: [PATCH 06/14] chore: denoify & format --- deno_dist/middleware/body-limit/index.ts | 131 ++++++++++++++++++++++ deno_dist/middleware/body-parser/index.ts | 84 -------------- 2 files changed, 131 insertions(+), 84 deletions(-) create mode 100644 deno_dist/middleware/body-limit/index.ts delete mode 100644 deno_dist/middleware/body-parser/index.ts diff --git a/deno_dist/middleware/body-limit/index.ts b/deno_dist/middleware/body-limit/index.ts new file mode 100644 index 000000000..1a27ac87e --- /dev/null +++ b/deno_dist/middleware/body-limit/index.ts @@ -0,0 +1,131 @@ +import type { Context, MiddlewareHandler } from '../../index.ts' + +const bodyTypes = ['body', 'json', 'form', 'text'] as const + +type bodyLimitOptions = { + type?: typeof bodyTypes[number] + limit?: number + handler?: (c: Context) => Response +}[] + +type bodyLimitObject = { + body?: bodyLimitOptions[number] + json?: bodyLimitOptions[number] + form?: bodyLimitOptions[number] + text?: bodyLimitOptions[number] +} + +const defaultOptions: bodyLimitOptions = bodyTypes.map((bodyType) => { + return { + type: bodyType, + limit: NaN, + handler: (c: Context) => { + return c.text('413 Request Entity Too Large', 413) + }, + } +}) + +const allowMethods = ['POST', 'PUT', 'PATCH'] + +const deleteSameType = (options: bodyLimitOptions): bodyLimitObject => { + const objects: bodyLimitObject = {} + + for (let i = 0, len = options.length; i < len; i++) { + const option = options[i] + objects[option.type ?? 'body'] = { + type: 'body', + limit: NaN, + handler: (c: Context) => { + return c.text('413 Request Entity Too Large', 413) + }, + ...option, + } + } + + return objects +} + +/** + * Built-in Middleware for limit body size + * + * @example + * ```ts + * app.post( + * '/hello', + * bodyLimit({ + * type: 'text', // body | json | form | text + * limit: 15 * Uint.b, // byte, + * handler: (c) => { + * return c.text("oveflow :("); + * } + * }), + * (c) => { + * return c.text('pass :)') + * } + * ) + * + * /** + * body: all type + * text: taxt/plain + * json: application/json + * form: application/x-www-form-urlencoded + * *\/ + * ``` + */ +export const bodyLimit = ( + options: bodyLimitOptions | bodyLimitOptions[number] = defaultOptions +): MiddlewareHandler => { + const limitOptions: bodyLimitObject = deleteSameType([...defaultOptions, ...[options].flat()]) + + return async function bodylimit(c: Context, next: () => Promise) { + if (allowMethods.includes(c.req.method.toUpperCase())) { + const req = c.req.raw.clone() + const blob = await req.blob() + const bodySize = blob.size + + let type: typeof bodyTypes[number] = 'body' + const ContentType = req.headers.get('Content-Type')?.trim() ?? '' + + if (ContentType.startsWith('text/plain')) { + type = 'text' + } else if (ContentType.startsWith('application/json')) { + type = 'json' + } else if (ContentType.startsWith('application/x-www-form-urlencoded')) { + type = 'form' + } + + const limitOption = limitOptions[type] + const bodyLimitOption = limitOptions['body'] + + if ( + limitOption && + limitOption.limit && + limitOption.handler && + !isNaN(limitOption.limit) && + bodySize > limitOption.limit + ) { + return limitOption.handler(c) + } else if ( + bodyLimitOption && + bodyLimitOption.limit && + bodyLimitOption.handler && + !isNaN(bodyLimitOption.limit) && + bodySize > bodyLimitOption.limit + ) { + return bodyLimitOption.handler(c) + } + } + + await next() + } +} + +/** + * Uint any + * @example + * ```ts + * const limit = 100 * Uint.kb // 100kb + * const limit2 = 1 * Unit.gb // 1gb + * ``` + */ +export const Uint = { b: 1, kb: 1000, mb: 1000 ** 2, gb: 1000 ** 3, tb: 1000 ** 4, pb: 1000 ** 5 } diff --git a/deno_dist/middleware/body-parser/index.ts b/deno_dist/middleware/body-parser/index.ts deleted file mode 100644 index 40803a3d0..000000000 --- a/deno_dist/middleware/body-parser/index.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { Context, MiddlewareHandler } from '../../index.ts' - -type bodyParserOptions = { - type?: 'body' | 'json' | 'form' | 'text' - limit?: number - handler?: (c: Context) => Response -} - -const defaultOptions: bodyParserOptions = { - type: 'body', - limit: 0, - handler: (c: Context) => { - return c.text('413 Request Entity Too Large', 413) - }, -} - -const allowMethods = ['POST', 'PUT', 'PATCH'] - -export const bodyParser = ( - options: bodyParserOptions = defaultOptions -): MiddlewareHandler<{ - Variables: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - body: () => T - } -}> => { - const parseOptions: bodyParserOptions = { - ...defaultOptions, - ...options, - } - - return async function bodyParse(c: Context, next: () => Promise) { - if ( - allowMethods.includes(c.req.method.toUpperCase()) && - parseOptions.handler && - parseOptions.limit && - parseOptions.type - ) { - const req = c.req.raw.clone() - const blob = await req.blob() - const bodySize = blob.size - - if (parseOptions.limit !== 0 && bodySize >= parseOptions.limit) { - return parseOptions.handler(c) - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let parsedData: any = blob - - switch (parseOptions.type) { - case 'body': - parsedData = blob - break - case 'text': - parsedData = await blob.text() - break - case 'json': - parsedData = JSON.parse(await blob.text()) - break - case 'form': - parsedData = await c.req.formData() - break - default: - parsedData = await blob.text() - break - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - c.set('body', () => parsedData as T) - } - - await next() - } -} - -/** - * Uint any - * @example - * ```ts - * const limit = 100 * Uint.kb // 100kb - * const limit2 = 1 * Unit.gb // 1gb - * ``` - */ -export const Uint = { b: 1, kb: 1000, mb: 1000 ** 2, gb: 1000 ** 3, tb: 1000 ** 4, pb: 1000 ** 5 } From fd12e58318851b32940dd7147db7e2e23311f07a Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Sat, 27 Jan 2024 00:41:29 +0000 Subject: [PATCH 07/14] fix: fix typo --- deno_dist/middleware/body-limit/index.ts | 8 +++---- src/middleware/body-limit/index.test.ts | 28 ++++++++++++------------ src/middleware/body-limit/index.ts | 8 +++---- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/deno_dist/middleware/body-limit/index.ts b/deno_dist/middleware/body-limit/index.ts index 1a27ac87e..9559c5883 100644 --- a/deno_dist/middleware/body-limit/index.ts +++ b/deno_dist/middleware/body-limit/index.ts @@ -54,7 +54,7 @@ const deleteSameType = (options: bodyLimitOptions): bodyLimitObject => { * '/hello', * bodyLimit({ * type: 'text', // body | json | form | text - * limit: 15 * Uint.b, // byte, + * limit: 15 * Unit.b, // byte, * handler: (c) => { * return c.text("oveflow :("); * } @@ -121,11 +121,11 @@ export const bodyLimit = ( } /** - * Uint any + * Unit any * @example * ```ts - * const limit = 100 * Uint.kb // 100kb + * const limit = 100 * Unit.kb // 100kb * const limit2 = 1 * Unit.gb // 1gb * ``` */ -export const Uint = { b: 1, kb: 1000, mb: 1000 ** 2, gb: 1000 ** 3, tb: 1000 ** 4, pb: 1000 ** 5 } +export const Unit = { b: 1, kb: 1024, mb: 1024 ** 2, gb: 1024 ** 3, tb: 1024 ** 4, pb: 1024 ** 5 } diff --git a/src/middleware/body-limit/index.test.ts b/src/middleware/body-limit/index.test.ts index bfa96dd04..8ee76fd1f 100644 --- a/src/middleware/body-limit/index.test.ts +++ b/src/middleware/body-limit/index.test.ts @@ -1,5 +1,5 @@ import { Hono } from '../../hono' -import { Uint, bodyLimit } from '.' +import { Unit, bodyLimit } from '.' describe('bodyLimit by Middleware', () => { const app = new Hono() @@ -26,7 +26,7 @@ describe('bodyLimit by Middleware', () => { app.post( '/body-limit-15byte', bodyLimit({ - limit: 15 * Uint.b, + limit: 15 * Unit.b, }), (c) => { return c.text('yes') @@ -59,7 +59,7 @@ describe('bodyLimit by Middleware', () => { '/text-limit-15byte', bodyLimit({ type: 'text', - limit: 15 * Uint.b, + limit: 15 * Unit.b, }), (c) => { return c.text('yes') @@ -92,7 +92,7 @@ describe('bodyLimit by Middleware', () => { '/json-limit-35byte', bodyLimit({ type: 'json', - limit: 35 * Uint.b, + limit: 35 * Unit.b, }), (c) => { return c.text('yes') @@ -131,7 +131,7 @@ describe('bodyLimit by Middleware', () => { '/form-limit-300byte', bodyLimit({ type: 'form', - limit: 300 * Uint.b, + limit: 300 * Unit.b, }), (c) => { return c.text('yes') @@ -170,7 +170,7 @@ describe('bodyLimit by Middleware', () => { '/text-limit-15byte-custom', bodyLimit({ type: 'text', - limit: 15 * Uint.b, + limit: 15 * Unit.b, handler: (c) => { return c.text('no', 413) }, @@ -195,7 +195,7 @@ describe('bodyLimit by Middleware', () => { '/json-limit-35byte-custom', bodyLimit({ type: 'json', - limit: 35 * Uint.b, + limit: 35 * Unit.b, handler: (c) => { return c.text('no', 413) }, @@ -224,14 +224,14 @@ describe('bodyLimit by Middleware', () => { bodyLimit([ { type: 'json', - limit: 35 * Uint.b, + limit: 35 * Unit.b, handler: (c) => { return c.text('no', 413) }, }, { type: 'text', - limit: 35 * Uint.b, + limit: 35 * Unit.b, handler: (c) => { return c.text('no', 413) }, @@ -267,13 +267,13 @@ describe('bodyLimit by Middleware', () => { expect(await res.text()).toBe('no') }) - it('Uint test', () => { - let beforeSize = 1 / 1000 + it('Unit test', () => { + let beforeSize = 1 / 1024 - for (let i = 0, keys = Object.keys(Uint), len = keys.length; i < len; i++) { + for (let i = 0, keys = Object.keys(Unit), len = keys.length; i < len; i++) { // @ts-expect-error: - const size = Uint[keys[i]] - expect(size === beforeSize * 1000).toBeTruthy() + const size = Unit[keys[i]] + expect(size === beforeSize * 1024).toBeTruthy() beforeSize = size } }) diff --git a/src/middleware/body-limit/index.ts b/src/middleware/body-limit/index.ts index 173ae9a76..8d0ad2635 100644 --- a/src/middleware/body-limit/index.ts +++ b/src/middleware/body-limit/index.ts @@ -54,7 +54,7 @@ const deleteSameType = (options: bodyLimitOptions): bodyLimitObject => { * '/hello', * bodyLimit({ * type: 'text', // body | json | form | text - * limit: 15 * Uint.b, // byte, + * limit: 15 * Unit.b, // byte, * handler: (c) => { * return c.text("oveflow :("); * } @@ -121,11 +121,11 @@ export const bodyLimit = ( } /** - * Uint any + * Unit any * @example * ```ts - * const limit = 100 * Uint.kb // 100kb + * const limit = 100 * Unit.kb // 100kb * const limit2 = 1 * Unit.gb // 1gb * ``` */ -export const Uint = { b: 1, kb: 1000, mb: 1000 ** 2, gb: 1000 ** 3, tb: 1000 ** 4, pb: 1000 ** 5 } +export const Unit = { b: 1, kb: 1024, mb: 1024 ** 2, gb: 1024 ** 3, tb: 1024 ** 4, pb: 1024 ** 5 } From 7eca736239b4eb435f0d0879125d5fb7f1db62ff Mon Sep 17 00:00:00 2001 From: Ame_x Edam Date: Sat, 27 Jan 2024 00:49:04 +0000 Subject: [PATCH 08/14] rename --- deno_dist/middleware/body-limit/index.ts | 16 ++++++++-------- src/middleware/body-limit/index.test.ts | 16 ++++++++-------- src/middleware/body-limit/index.ts | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/deno_dist/middleware/body-limit/index.ts b/deno_dist/middleware/body-limit/index.ts index 9559c5883..878b0d06c 100644 --- a/deno_dist/middleware/body-limit/index.ts +++ b/deno_dist/middleware/body-limit/index.ts @@ -4,7 +4,7 @@ const bodyTypes = ['body', 'json', 'form', 'text'] as const type bodyLimitOptions = { type?: typeof bodyTypes[number] - limit?: number + maxSize?: number handler?: (c: Context) => Response }[] @@ -34,7 +34,7 @@ const deleteSameType = (options: bodyLimitOptions): bodyLimitObject => { const option = options[i] objects[option.type ?? 'body'] = { type: 'body', - limit: NaN, + maxSize: NaN, handler: (c: Context) => { return c.text('413 Request Entity Too Large', 413) }, @@ -99,18 +99,18 @@ export const bodyLimit = ( if ( limitOption && - limitOption.limit && + limitOption.maxSize && limitOption.handler && - !isNaN(limitOption.limit) && - bodySize > limitOption.limit + !isNaN(limitOption.maxSize) && + bodySize > limitOption.maxSize ) { return limitOption.handler(c) } else if ( bodyLimitOption && - bodyLimitOption.limit && + bodyLimitOption.maxSize && bodyLimitOption.handler && - !isNaN(bodyLimitOption.limit) && - bodySize > bodyLimitOption.limit + !isNaN(bodyLimitOption.maxSize) && + bodySize > bodyLimitOption.maxSize ) { return bodyLimitOption.handler(c) } diff --git a/src/middleware/body-limit/index.test.ts b/src/middleware/body-limit/index.test.ts index 8ee76fd1f..35669c81f 100644 --- a/src/middleware/body-limit/index.test.ts +++ b/src/middleware/body-limit/index.test.ts @@ -26,7 +26,7 @@ describe('bodyLimit by Middleware', () => { app.post( '/body-limit-15byte', bodyLimit({ - limit: 15 * Unit.b, + maxSize: 15 * Unit.b, }), (c) => { return c.text('yes') @@ -59,7 +59,7 @@ describe('bodyLimit by Middleware', () => { '/text-limit-15byte', bodyLimit({ type: 'text', - limit: 15 * Unit.b, + maxSize: 15 * Unit.b, }), (c) => { return c.text('yes') @@ -92,7 +92,7 @@ describe('bodyLimit by Middleware', () => { '/json-limit-35byte', bodyLimit({ type: 'json', - limit: 35 * Unit.b, + maxSize: 35 * Unit.b, }), (c) => { return c.text('yes') @@ -131,7 +131,7 @@ describe('bodyLimit by Middleware', () => { '/form-limit-300byte', bodyLimit({ type: 'form', - limit: 300 * Unit.b, + maxSize: 300 * Unit.b, }), (c) => { return c.text('yes') @@ -170,7 +170,7 @@ describe('bodyLimit by Middleware', () => { '/text-limit-15byte-custom', bodyLimit({ type: 'text', - limit: 15 * Unit.b, + maxSize: 15 * Unit.b, handler: (c) => { return c.text('no', 413) }, @@ -195,7 +195,7 @@ describe('bodyLimit by Middleware', () => { '/json-limit-35byte-custom', bodyLimit({ type: 'json', - limit: 35 * Unit.b, + maxSize: 35 * Unit.b, handler: (c) => { return c.text('no', 413) }, @@ -224,14 +224,14 @@ describe('bodyLimit by Middleware', () => { bodyLimit([ { type: 'json', - limit: 35 * Unit.b, + maxSize: 35 * Unit.b, handler: (c) => { return c.text('no', 413) }, }, { type: 'text', - limit: 35 * Unit.b, + maxSize: 35 * Unit.b, handler: (c) => { return c.text('no', 413) }, diff --git a/src/middleware/body-limit/index.ts b/src/middleware/body-limit/index.ts index 8d0ad2635..e04786799 100644 --- a/src/middleware/body-limit/index.ts +++ b/src/middleware/body-limit/index.ts @@ -4,7 +4,7 @@ const bodyTypes = ['body', 'json', 'form', 'text'] as const type bodyLimitOptions = { type?: typeof bodyTypes[number] - limit?: number + maxSize?: number handler?: (c: Context) => Response }[] @@ -34,7 +34,7 @@ const deleteSameType = (options: bodyLimitOptions): bodyLimitObject => { const option = options[i] objects[option.type ?? 'body'] = { type: 'body', - limit: NaN, + maxSize: NaN, handler: (c: Context) => { return c.text('413 Request Entity Too Large', 413) }, @@ -99,18 +99,18 @@ export const bodyLimit = ( if ( limitOption && - limitOption.limit && + limitOption.maxSize && limitOption.handler && - !isNaN(limitOption.limit) && - bodySize > limitOption.limit + !isNaN(limitOption.maxSize) && + bodySize > limitOption.maxSize ) { return limitOption.handler(c) } else if ( bodyLimitOption && - bodyLimitOption.limit && + bodyLimitOption.maxSize && bodyLimitOption.handler && - !isNaN(bodyLimitOption.limit) && - bodySize > bodyLimitOption.limit + !isNaN(bodyLimitOption.maxSize) && + bodySize > bodyLimitOption.maxSize ) { return bodyLimitOption.handler(c) } From 74c967525e1b34d262ff96ebdb8a276ae2b4e365 Mon Sep 17 00:00:00 2001 From: EdamAme <121654029+EdamAme-x@users.noreply.github.com> Date: Sun, 28 Jan 2024 01:22:49 +0000 Subject: [PATCH 09/14] fix --- package.json | 1052 ++++++++++++++-------------- src/middleware/body-limit/index.ts | 31 +- yarn.lock | 164 ++++- 3 files changed, 701 insertions(+), 546 deletions(-) diff --git a/package.json b/package.json index 4caf5deeb..f63a55ed8 100644 --- a/package.json +++ b/package.json @@ -1,540 +1,512 @@ -{ - "name": "hono", - "version": "4.0.0-rc.2", - "description": "Ultrafast web framework for the Edges", - "main": "dist/cjs/index.js", - "type": "module", - "module": "dist/index.js", - "types": "dist/types/index.d.ts", - "files": [ - "dist" - ], - "scripts": { - "test": "tsc --noEmit && vitest --run && vitest -c .vitest.config/jsx-runtime-default.ts --run && vitest -c .vitest.config/jsx-runtime-dom.ts --run", - "test:watch": "vitest --watch", - "test:deno": "env NAME=Deno deno test --allow-read --allow-env --allow-write -c runtime_tests/deno/deno.json runtime_tests/deno && deno test --no-lock -c runtime_tests/deno-jsx/deno.precompile.json runtime_tests/deno-jsx && deno test --no-lock -c runtime_tests/deno-jsx/deno.react-jsx.json runtime_tests/deno-jsx", - "test:bun": "env NAME=Bun bun test --jsx-import-source ../../src/jsx runtime_tests/bun/index.test.tsx", - "test:fastly": "vitest --run --config ./runtime_tests/fastly/vitest.config.ts", - "test:node": "env NAME=Node vitest --run --config ./runtime_tests/node/vitest.config.ts", - "test:wrangler": "vitest --run --config ./runtime_tests/wrangler/vitest.config.ts", - "test:lambda": "env NAME=Node vitest --run --config ./runtime_tests/lambda/vitest.config.ts", - "test:lambda-edge": "env NAME=Node vitest --run --config ./runtime_tests/lambda-edge/vitest.config.ts", - "test:all": "yarn test && yarn test:deno && yarn test:bun && yarn test:fastly && yarn test:node && yarn test:wrangler && yarn test:lambda && yarn test:lambda-edge", - "lint": "eslint --ext js,ts,tsx src runtime_tests", - "lint:fix": "eslint --ext js,ts,tsx src runtime_tests --fix", - "format": "prettier --check \"src/**/*.{js,ts,tsx}\" \"runtime_tests/**/*.{js,ts,tsx}\"", - "format:fix": "prettier --write \"src/**/*.{js,ts,tsx}\" \"runtime_tests/**/*.{js,ts,tsx}\"", - "denoify": "rimraf deno_dist && denoify && rimraf \"deno_dist/**/*.test.{ts,tsx}\"", - "copy:package.cjs.json": "cp ./package.cjs.json ./dist/cjs/package.json && cp ./package.cjs.json ./dist/types/package.json ", - "build": "rimraf dist && tsx ./build.ts && yarn copy:package.cjs.json", - "postbuild": "publint", - "watch": "rimraf dist && tsx ./build.ts --watch && yarn copy:package.cjs.json", - "coverage": "vitest --run --coverage", - "prerelease": "yarn denoify && yarn test:deno && yarn build", - "release": "np" - }, - "exports": { - ".": { - "types": "./dist/types/index.d.ts", - "import": "./dist/index.js", - "require": "./dist/cjs/index.js" - }, - "./types": { - "types": "./dist/types/types.d.ts", - "import": "./dist/types.js", - "require": "./dist/cjs/types.js" - }, - "./hono-base": { - "types": "./dist/types/hono-base.d.ts", - "import": "./dist/hono-base.js", - "require": "./dist/cjs/hono-base.js" - }, - "./tiny": { - "types": "./dist/types/preset/tiny.d.ts", - "import": "./dist/preset/tiny.js", - "require": "./dist/cjs/preset/tiny.js" - }, - "./quick": { - "types": "./dist/types/preset/quick.d.ts", - "import": "./dist/preset/quick.js", - "require": "./dist/cjs/preset/quick.js" - }, - "./http-exception": { - "types": "./dist/types/http-exception.d.ts", - "import": "./dist/http-exception.js", - "require": "./dist/cjs/http-exception.js" - }, - "./basic-auth": { - "types": "./dist/types/middleware/basic-auth/index.d.ts", - "import": "./dist/middleware/basic-auth/index.js", - "require": "./dist/cjs/middleware/basic-auth/index.js" - }, - "./bearer-auth": { - "types": "./dist/types/middleware/bearer-auth/index.d.ts", - "import": "./dist/middleware/bearer-auth/index.js", - "require": "./dist/cjs/middleware/bearer-auth/index.js" - }, - "./cache": { - "types": "./dist/types/middleware/cache/index.d.ts", - "import": "./dist/middleware/cache/index.js", - "require": "./dist/cjs/middleware/cache/index.js" - }, - "./cookie": { - "types": "./dist/types/helper/cookie/index.d.ts", - "import": "./dist/helper/cookie/index.js", - "require": "./dist/cjs/helper/cookie/index.js" - }, - "./accepts": { - "types": "./dist/types/helper/accepts/index.d.ts", - "import": "./dist/helper/accepts/index.js", - "require": "./dist/cjs/helper/accepts/index.js" - }, - "./compress": { - "types": "./dist/types/middleware/compress/index.d.ts", - "import": "./dist/middleware/compress/index.js", - "require": "./dist/cjs/middleware/compress/index.js" - }, - "./cors": { - "types": "./dist/types/middleware/cors/index.d.ts", - "import": "./dist/middleware/cors/index.js", - "require": "./dist/cjs/middleware/cors/index.js" - }, - "./csrf": { - "types": "./dist/types/middleware/csrf/index.d.ts", - "import": "./dist/middleware/csrf/index.js", - "require": "./dist/cjs/middleware/csrf/index.js" - }, - "./etag": { - "types": "./dist/types/middleware/etag/index.d.ts", - "import": "./dist/middleware/etag/index.js", - "require": "./dist/cjs/middleware/etag/index.js" - }, - "./html": { - "types": "./dist/types/helper/html/index.d.ts", - "import": "./dist/helper/html/index.js", - "require": "./dist/cjs/helper/html/index.js" - }, - "./css": { - "types": "./dist/types/helper/css/index.d.ts", - "import": "./dist/helper/css/index.js", - "require": "./dist/cjs/helper/css/index.js" - }, - "./jsx": { - "types": "./dist/types/jsx/index.d.ts", - "import": "./dist/jsx/index.js", - "require": "./dist/cjs/jsx/index.js" - }, - "./jsx/jsx-dev-runtime": { - "types": "./dist/types/jsx/jsx-dev-runtime.d.ts", - "import": "./dist/jsx/jsx-dev-runtime.js", - "require": "./dist/cjs/jsx/jsx-dev-runtime.js" - }, - "./jsx/jsx-runtime": { - "types": "./dist/types/jsx/jsx-runtime.d.ts", - "import": "./dist/jsx/jsx-runtime.js", - "require": "./dist/cjs/jsx/jsx-runtime.js" - }, - "./jsx/streaming": { - "types": "./dist/types/jsx/streaming.d.ts", - "import": "./dist/jsx/streaming.js", - "require": "./dist/cjs/jsx/streaming.js" - }, - "./jsx-renderer": { - "types": "./dist/types/middleware/jsx-renderer/index.d.ts", - "import": "./dist/middleware/jsx-renderer/index.js", - "require": "./dist/cjs/middleware/jsx-renderer/index.js" - }, - "./jsx/dom": { - "types": "./dist/types/jsx/dom/index.d.ts", - "import": "./dist/jsx/dom/index.js", - "require": "./dist/cjs/jsx/dom/index.js" - }, - "./jsx/dom/jsx-dev-runtime": { - "types": "./dist/types/jsx/dom/jsx-dev-runtime.d.ts", - "import": "./dist/jsx/dom/jsx-dev-runtime.js", - "require": "./dist/cjs/jsx/dom/jsx-dev-runtime.js" - }, - "./jsx/dom/jsx-runtime": { - "types": "./dist/types/jsx/dom/jsx-runtime.d.ts", - "import": "./dist/jsx/dom/jsx-runtime.js", - "require": "./dist/cjs/jsx/dom/jsx-runtime.js" - }, - "./jsx/dom/css": { - "types": "./dist/types/jsx/dom/css.d.ts", - "import": "./dist/jsx/dom/css.js", - "require": "./dist/cjs/jsx/dom/css.js" - }, - "./jwt": { - "types": "./dist/types/middleware/jwt/index.d.ts", - "import": "./dist/middleware/jwt/index.js", - "require": "./dist/cjs/middleware/jwt/index.js" - }, - "./timing": { - "types": "./dist/types/middleware/timing/index.d.ts", - "import": "./dist/middleware/timing/index.js", - "require": "./dist/cjs/middleware/timing/index.js" - }, - "./logger": { - "types": "./dist/types/middleware/logger/index.d.ts", - "import": "./dist/middleware/logger/index.js", - "require": "./dist/cjs/middleware/logger/index.js" - }, - "./powered-by": { - "types": "./dist/types/middleware/powered-by/index.d.ts", - "import": "./dist/middleware/powered-by/index.js", - "require": "./dist/cjs/middleware/powered-by/index.js" - }, - "./pretty-json": { - "types": "./dist/types/middleware/pretty-json/index.d.ts", - "import": "./dist/middleware/pretty-json/index.js", - "require": "./dist/cjs/middleware/pretty-json/index.js" - }, - "./secure-headers": { - "types": "./dist/types/middleware/secure-headers/index.d.ts", - "import": "./dist/middleware/secure-headers/index.js", - "require": "./dist/cjs/middleware/secure-headers/index.js" - }, - "./ssg": { - "types": "./dist/types/helper/ssg/index.d.ts", - "import": "./dist/helper/ssg/index.js", - "require": "./dist/cjs/helper/ssg/index.js" - }, - "./streaming": { - "types": "./dist/types/helper/streaming/index.d.ts", - "import": "./dist/helper/streaming/index.js", - "require": "./dist/cjs/helper/streaming/index.js" - }, - "./validator": { - "types": "./dist/types/validator/index.d.ts", - "import": "./dist/validator/index.js", - "require": "./dist/cjs/validator/index.js" - }, - "./router": { - "types": "./dist/types/router.d.ts", - "import": "./dist/router.js", - "require": "./dist/cjs/router.js" - }, - "./router/reg-exp-router": { - "types": "./dist/types/router/reg-exp-router/index.d.ts", - "import": "./dist/router/reg-exp-router/index.js", - "require": "./dist/cjs/router/reg-exp-router/index.js" - }, - "./router/smart-router": { - "types": "./dist/types/router/smart-router/index.d.ts", - "import": "./dist/router/smart-router/index.js", - "require": "./dist/cjs/router/smart-router/index.js" - }, - "./router/trie-router": { - "types": "./dist/types/router/trie-router/index.d.ts", - "import": "./dist/router/trie-router/index.js", - "require": "./dist/cjs/router/trie-router/index.js" - }, - "./router/pattern-router": { - "types": "./dist/types/router/pattern-router/index.d.ts", - "import": "./dist/router/pattern-router/index.js", - "require": "./dist/cjs/router/pattern-router/index.js" - }, - "./router/linear-router": { - "types": "./dist/types/router/linear-router/index.d.ts", - "import": "./dist/router/linear-router/index.js", - "require": "./dist/cjs/router/linear-router/index.js" - }, - "./utils/jwt": { - "types": "./dist/types/utils/jwt/index.d.ts", - "import": "./dist/utils/jwt/index.js", - "require": "./dist/cjs/utils/jwt/index.js" - }, - "./utils/*": { - "types": "./dist/types/utils/*.d.ts", - "import": "./dist/utils/*.js", - "require": "./dist/cjs/utils/*.js" - }, - "./client": { - "types": "./dist/types/client/index.d.ts", - "import": "./dist/client/index.js", - "require": "./dist/cjs/client/index.js" - }, - "./adapter": { - "types": "./dist/types/helper/adapter/index.d.ts", - "import": "./dist/helper/adapter/index.js", - "require": "./dist/cjs/helper/adapter/index.js" - }, - "./factory": { - "types": "./dist/types/helper/factory/index.d.ts", - "import": "./dist/helper/factory/index.js", - "require": "./dist/cjs/helper/factory/index.js" - }, - "./cloudflare-workers": { - "types": "./dist/types/adapter/cloudflare-workers/index.d.ts", - "import": "./dist/adapter/cloudflare-workers/index.js", - "require": "./dist/cjs/adapter/cloudflare-workers/index.js" - }, - "./cloudflare-pages": { - "types": "./dist/types/adapter/cloudflare-pages/index.d.ts", - "import": "./dist/adapter/cloudflare-pages/index.js", - "require": "./dist/cjs/adapter/cloudflare-pages/index.js" - }, - "./deno": { - "types": "./dist/types/adapter/deno/index.d.ts", - "import": "./dist/adapter/deno/index.js", - "require": "./dist/cjs/adapter/deno/index.js" - }, - "./bun": { - "types": "./dist/types/adapter/bun/index.d.ts", - "import": "./dist/adapter/bun/index.js", - "require": "./dist/cjs/adapter/bun/index.js" - }, - "./aws-lambda": { - "types": "./dist/types/adapter/aws-lambda/index.d.ts", - "import": "./dist/adapter/aws-lambda/index.js", - "require": "./dist/cjs/adapter/aws-lambda/index.js" - }, - "./vercel": { - "types": "./dist/types/adapter/vercel/index.d.ts", - "import": "./dist/adapter/vercel/index.js", - "require": "./dist/cjs/adapter/vercel/index.js" - }, - "./netlify": { - "types": "./dist/types/adapter/netlify/index.d.ts", - "import": "./dist/adapter/netlify/index.js", - "require": "./dist/cjs/adapter/netlify/index.js" - }, - "./lambda-edge": { - "types": "./dist/types/adapter/lambda-edge/index.d.ts", - "import": "./dist/adapter/lambda-edge/index.js", - "require": "./dist/cjs/adapter/lambda-edge/index.js" - }, - "./testing": { - "types": "./dist/types/helper/testing/index.d.ts", - "import": "./dist/helper/testing/index.js", - "require": "./dist/cjs/helper/testing/index.js" - }, - "./dev": { - "types": "./dist/types/helper/dev/index.d.ts", - "import": "./dist/helper/dev/index.js", - "require": "./dist/cjs/helper/dev/index.js" - } - }, - "typesVersions": { - "*": { - "types": [ - "./dist/types/types" - ], - "hono-base": [ - "./dist/types/hono-base" - ], - "tiny": [ - "./dist/types/preset/tiny" - ], - "quick": [ - "./dist/types/preset/quick" - ], - "http-exception": [ - "./dist/types/http-exception" - ], - "basic-auth": [ - "./dist/types/middleware/basic-auth" - ], - "bearer-auth": [ - "./dist/types/middleware/bearer-auth" - ], - "cache": [ - "./dist/types/middleware/cache" - ], - "cookie": [ - "./dist/types/helper/cookie" - ], - "compress": [ - "./dist/types/middleware/compress" - ], - "cors": [ - "./dist/types/middleware/cors" - ], - "csrf": [ - "./dist/types/middleware/csrf" - ], - "etag": [ - "./dist/types/middleware/etag" - ], - "html": [ - "./dist/types/helper/html" - ], - "css": [ - "./dist/types/helper/css" - ], - "jsx": [ - "./dist/types/jsx" - ], - "jsx/jsx-runtime": [ - "./dist/types/jsx/jsx-runtime.d.ts" - ], - "jsx/jsx-dev-runtime": [ - "./dist/types/jsx/jsx-dev-runtime.d.ts" - ], - "jsx/streaming": [ - "./dist/types/jsx/streaming.d.ts" - ], - "jsx-renderer": [ - "./dist/types/middleware/jsx-renderer" - ], - "jsx/dom": [ - "./dist/types/jsx/dom" - ], - "jsx/dom/css": [ - "./dist/types/jsx/dom/css.d.ts" - ], - "jwt": [ - "./dist/types/middleware/jwt" - ], - "timing": [ - "./dist/types/middleware/timing" - ], - "logger": [ - "./dist/types/middleware/logger" - ], - "powered-by": [ - "./dist/types/middleware/powered-by" - ], - "pretty-json": [ - "./dist/types/middleware/pretty-json" - ], - "streaming": [ - "./dist/types/helper/streaming" - ], - "ssg": [ - "./dist/types/helper/ssg" - ], - "secure-headers": [ - "./dist/types/middleware/secure-headers" - ], - "validator": [ - "./dist/types/validator/index.d.ts" - ], - "router": [ - "./dist/types/router.d.ts" - ], - "router/reg-exp-router": [ - "./dist/types/router/reg-exp-router/router.d.ts" - ], - "router/smart-router": [ - "./dist/types/router/smart-router/router.d.ts" - ], - "router/trie-router": [ - "./dist/types/router/trie-router/router.d.ts" - ], - "router/pattern-router": [ - "./dist/types/router/pattern-router/router.d.ts" - ], - "router/linear-router": [ - "./dist/types/router/linear-router/router.d.ts" - ], - "utils/jwt": [ - "./dist/types/utils/jwt/index.d.ts" - ], - "utils/*": [ - "./dist/types/utils/*" - ], - "client": [ - "./dist/types/client/index.d.ts" - ], - "adapter": [ - "./dist/types/helper/adapter/index.d.ts" - ], - "factory": [ - "./dist/types/helper/factory/index.d.ts" - ], - "cloudflare-workers": [ - "./dist/types/adapter/cloudflare-workers" - ], - "cloudflare-pages": [ - "./dist/types/adapter/cloudflare-pages" - ], - "deno": [ - "./dist/types/adapter/deno" - ], - "bun": [ - "./dist/types/adapter/bun" - ], - "nextjs": [ - "./dist/types/adapter/nextjs" - ], - "aws-lambda": [ - "./dist/types/adapter/aws-lambda" - ], - "vercel": [ - "./dist/types/adapter/vercel" - ], - "lambda-edge": [ - "./dist/types/adapter/lambda-edge" - ], - "testing": [ - "./dist/types/helper/testing" - ], - "dev": [ - "./dist/types/helper/dev" - ] - } - }, - "author": "Yusuke Wada (https://github.com/yusukebe)", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/honojs/hono.git" - }, - "publishConfig": { - "registry": "https://registry.npmjs.org" - }, - "homepage": "https://hono.dev", - "keywords": [ - "hono", - "web", - "app", - "http", - "application", - "framework", - "router", - "cloudflare", - "workers", - "fastly", - "compute@edge", - "deno", - "bun", - "lambda", - "nodejs" - ], - "devDependencies": { - "@cloudflare/workers-types": "^4.20231121.0", - "@hono/eslint-config": "^0.0.3", - "@hono/node-server": "^1.3.3", - "@types/crypto-js": "^4.1.1", - "@types/glob": "^8.0.0", - "@types/jsdom": "^21.1.4", - "@types/node": "^20.8.2", - "@types/node-fetch": "^2.6.2", - "@types/supertest": "^2.0.12", - "@vitest/coverage-v8": "^1.1.0", - "arg": "^5.0.2", - "crypto-js": "^4.1.1", - "denoify": "^1.6.6", - "esbuild": "^0.15.12", - "eslint": "^8.55.0", - "form-data": "^4.0.0", - "jsdom": "^22.1.0", - "msw": "^1.0.0", - "node-fetch": "2", - "np": "^7.7.0", - "prettier": "^2.6.2", - "publint": "^0.1.8", - "rimraf": "^3.0.2", - "supertest": "^6.3.3", - "tsx": "^3.11.0", - "typescript": "^5.3.3", - "vite-plugin-fastly-js-compute": "^0.4.2", - "vitest": "^1.1.0", - "wrangler": "3.17.1", - "zod": "^3.20.2" - }, - "engines": { - "node": ">=16.0.0" - } -} +{ + "name": "hono", + "version": "3.12.1", + "description": "Ultrafast web framework for the Edges", + "main": "dist/cjs/index.js", + "type": "module", + "module": "dist/index.js", + "types": "dist/types/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "test": "tsc --noEmit && vitest --run", + "test:deno": "env NAME=Deno deno test --allow-read --allow-env runtime_tests/deno && deno test --no-lock -c runtime_tests/deno-jsx/deno.precompile.json runtime_tests/deno-jsx && deno test --no-lock -c runtime_tests/deno-jsx/deno.react-jsx.json runtime_tests/deno-jsx", + "test:bun": "env NAME=Bun bun test --jsx-import-source ../../src/jsx runtime_tests/bun/index.test.tsx", + "test:fastly": "vitest --run --config ./runtime_tests/fastly/vitest.config.ts", + "test:lagon": "start-server-and-test \"lagon dev runtime_tests/lagon/index.ts -e runtime_tests/lagon/.env.lagon\" http://127.0.0.1:1234 \"yarn vitest --run runtime_tests/lagon/index.test.ts --config runtime_tests/lagon/vitest.config.ts\"", + "test:node": "env NAME=Node vitest --run --config ./runtime_tests/node/vitest.config.ts", + "test:wrangler": "vitest --run --config ./runtime_tests/wrangler/vitest.config.ts", + "test:lambda": "env NAME=Node vitest --run --config ./runtime_tests/lambda/vitest.config.ts", + "test:lambda-edge": "env NAME=Node vitest --run --config ./runtime_tests/lambda-edge/vitest.config.ts", + "test:all": "yarn test && yarn test:deno && yarn test:bun && yarn test:fastly && yarn test:lagon && yarn test:node && yarn test:wrangler && yarn test:lambda && yarn test:lambda-edge", + "lint": "eslint --ext js,ts src runtime_tests", + "lint:fix": "eslint --ext js,ts src runtime_tests --fix", + "format": "prettier --check 'src/**/*.{js,ts}' 'runtime_tests/**/*.{js,ts}'", + "format:fix": "prettier --write 'src/**/*.{js,ts}' 'runtime_tests/**/*.{js,ts}'", + "denoify": "rimraf deno_dist && denoify && rimraf 'deno_dist/**/*.test.{ts,tsx}'", + "copy:package.cjs.json": "cp ./package.cjs.json ./dist/cjs/package.json && cp ./package.cjs.json ./dist/types/package.json ", + "build": "rimraf dist && tsx ./build.ts && yarn copy:package.cjs.json", + "postbuild": "publint", + "watch": "rimraf dist && tsx ./build.ts --watch && yarn copy:package.cjs.json", + "coverage": "vitest --run --coverage", + "prerelease": "yarn denoify && yarn test:deno && yarn build", + "release": "np" + }, + "exports": { + ".": { + "types": "./dist/types/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/cjs/index.js" + }, + "./types": { + "types": "./dist/types/types.d.ts", + "import": "./dist/types.js", + "require": "./dist/cjs/types.js" + }, + "./hono-base": { + "types": "./dist/types/hono-base.d.ts", + "import": "./dist/hono-base.js", + "require": "./dist/cjs/hono-base.js" + }, + "./tiny": { + "types": "./dist/types/preset/tiny.d.ts", + "import": "./dist/preset/tiny.js", + "require": "./dist/cjs/preset/tiny.js" + }, + "./quick": { + "types": "./dist/types/preset/quick.d.ts", + "import": "./dist/preset/quick.js", + "require": "./dist/cjs/preset/quick.js" + }, + "./http-exception": { + "types": "./dist/types/http-exception.d.ts", + "import": "./dist/http-exception.js", + "require": "./dist/cjs/http-exception.js" + }, + "./basic-auth": { + "types": "./dist/types/middleware/basic-auth/index.d.ts", + "import": "./dist/middleware/basic-auth/index.js", + "require": "./dist/cjs/middleware/basic-auth/index.js" + }, + "./bearer-auth": { + "types": "./dist/types/middleware/bearer-auth/index.d.ts", + "import": "./dist/middleware/bearer-auth/index.js", + "require": "./dist/cjs/middleware/bearer-auth/index.js" + }, + "./body-limit": { + "types": "./dist/types/middleware/body-limit/index.d.ts", + "import": "./dist/middleware/body-limit/index.js", + "require": "./dist/cjs/middleware/body-limit/index.js" + }, + "./cache": { + "types": "./dist/types/middleware/cache/index.d.ts", + "import": "./dist/middleware/cache/index.js", + "require": "./dist/cjs/middleware/cache/index.js" + }, + "./cookie": { + "types": "./dist/types/helper/cookie/index.d.ts", + "import": "./dist/helper/cookie/index.js", + "require": "./dist/cjs/helper/cookie/index.js" + }, + "./compress": { + "types": "./dist/types/middleware/compress/index.d.ts", + "import": "./dist/middleware/compress/index.js", + "require": "./dist/cjs/middleware/compress/index.js" + }, + "./cors": { + "types": "./dist/types/middleware/cors/index.d.ts", + "import": "./dist/middleware/cors/index.js", + "require": "./dist/cjs/middleware/cors/index.js" + }, + "./csrf": { + "types": "./dist/types/middleware/csrf/index.d.ts", + "import": "./dist/middleware/csrf/index.js", + "require": "./dist/cjs/middleware/csrf/index.js" + }, + "./etag": { + "types": "./dist/types/middleware/etag/index.d.ts", + "import": "./dist/middleware/etag/index.js", + "require": "./dist/cjs/middleware/etag/index.js" + }, + "./html": { + "types": "./dist/types/helper/html/index.d.ts", + "import": "./dist/helper/html/index.js", + "require": "./dist/cjs/helper/html/index.js" + }, + "./css": { + "types": "./dist/types/helper/css/index.d.ts", + "import": "./dist/helper/css/index.js", + "require": "./dist/cjs/helper/css/index.js" + }, + "./jsx": { + "types": "./dist/types/jsx/index.d.ts", + "import": "./dist/jsx/index.js", + "require": "./dist/cjs/jsx/index.js" + }, + "./jsx/jsx-dev-runtime": { + "types": "./dist/types/jsx/jsx-dev-runtime.d.ts", + "import": "./dist/jsx/jsx-dev-runtime.js", + "require": "./dist/cjs/jsx/jsx-dev-runtime.js" + }, + "./jsx/jsx-runtime": { + "types": "./dist/types/jsx/jsx-runtime.d.ts", + "import": "./dist/jsx/jsx-runtime.js", + "require": "./dist/cjs/jsx/jsx-runtime.js" + }, + "./jsx/streaming": { + "types": "./dist/types/jsx/streaming.d.ts", + "import": "./dist/jsx/streaming.js", + "require": "./dist/cjs/jsx/streaming.js" + }, + "./jsx-renderer": { + "types": "./dist/types/middleware/jsx-renderer/index.d.ts", + "import": "./dist/middleware/jsx-renderer/index.js", + "require": "./dist/cjs/middleware/jsx-renderer/index.js" + }, + "./jwt": { + "types": "./dist/types/middleware/jwt/index.d.ts", + "import": "./dist/middleware/jwt/index.js", + "require": "./dist/cjs/middleware/jwt/index.js" + }, + "./timing": { + "types": "./dist/types/middleware/timing/index.d.ts", + "import": "./dist/middleware/timing/index.js", + "require": "./dist/cjs/middleware/timing/index.js" + }, + "./logger": { + "types": "./dist/types/middleware/logger/index.d.ts", + "import": "./dist/middleware/logger/index.js", + "require": "./dist/cjs/middleware/logger/index.js" + }, + "./powered-by": { + "types": "./dist/types/middleware/powered-by/index.d.ts", + "import": "./dist/middleware/powered-by/index.js", + "require": "./dist/cjs/middleware/powered-by/index.js" + }, + "./pretty-json": { + "types": "./dist/types/middleware/pretty-json/index.d.ts", + "import": "./dist/middleware/pretty-json/index.js", + "require": "./dist/cjs/middleware/pretty-json/index.js" + }, + "./secure-headers": { + "types": "./dist/types/middleware/secure-headers/index.d.ts", + "import": "./dist/middleware/secure-headers/index.js", + "require": "./dist/cjs/middleware/secure-headers/index.js" + }, + "./streaming": { + "types": "./dist/types/helper/streaming/index.d.ts", + "import": "./dist/helper/streaming/index.js", + "require": "./dist/cjs/helper/streaming/index.js" + }, + "./validator": { + "types": "./dist/types/validator/index.d.ts", + "import": "./dist/validator/index.js", + "require": "./dist/cjs/validator/index.js" + }, + "./router": { + "types": "./dist/types/router.d.ts", + "import": "./dist/router.js", + "require": "./dist/cjs/router.js" + }, + "./router/reg-exp-router": { + "types": "./dist/types/router/reg-exp-router/index.d.ts", + "import": "./dist/router/reg-exp-router/index.js", + "require": "./dist/cjs/router/reg-exp-router/index.js" + }, + "./router/smart-router": { + "types": "./dist/types/router/smart-router/index.d.ts", + "import": "./dist/router/smart-router/index.js", + "require": "./dist/cjs/router/smart-router/index.js" + }, + "./router/trie-router": { + "types": "./dist/types/router/trie-router/index.d.ts", + "import": "./dist/router/trie-router/index.js", + "require": "./dist/cjs/router/trie-router/index.js" + }, + "./router/pattern-router": { + "types": "./dist/types/router/pattern-router/index.d.ts", + "import": "./dist/router/pattern-router/index.js", + "require": "./dist/cjs/router/pattern-router/index.js" + }, + "./router/linear-router": { + "types": "./dist/types/router/linear-router/index.d.ts", + "import": "./dist/router/linear-router/index.js", + "require": "./dist/cjs/router/linear-router/index.js" + }, + "./utils/jwt": { + "types": "./dist/types/utils/jwt/index.d.ts", + "import": "./dist/utils/jwt/index.js", + "require": "./dist/cjs/utils/jwt/index.js" + }, + "./utils/*": { + "types": "./dist/types/utils/*.d.ts", + "import": "./dist/utils/*.js", + "require": "./dist/cjs/utils/*.js" + }, + "./client": { + "types": "./dist/types/client/index.d.ts", + "import": "./dist/client/index.js", + "require": "./dist/cjs/client/index.js" + }, + "./adapter": { + "types": "./dist/types/helper/adapter/index.d.ts", + "import": "./dist/helper/adapter/index.js", + "require": "./dist/cjs/helper/adapter/index.js" + }, + "./factory": { + "types": "./dist/types/helper/factory/index.d.ts", + "import": "./dist/helper/factory/index.js", + "require": "./dist/cjs/helper/factory/index.js" + }, + "./cloudflare-workers": { + "types": "./dist/types/adapter/cloudflare-workers/index.d.ts", + "import": "./dist/adapter/cloudflare-workers/index.js", + "require": "./dist/cjs/adapter/cloudflare-workers/index.js" + }, + "./cloudflare-pages": { + "types": "./dist/types/adapter/cloudflare-pages/index.d.ts", + "import": "./dist/adapter/cloudflare-pages/index.js", + "require": "./dist/cjs/adapter/cloudflare-pages/index.js" + }, + "./deno": { + "types": "./dist/types/adapter/deno/index.d.ts", + "import": "./dist/adapter/deno/index.js", + "require": "./dist/cjs/adapter/deno/index.js" + }, + "./bun": { + "types": "./dist/types/adapter/bun/index.d.ts", + "import": "./dist/adapter/bun/index.js", + "require": "./dist/cjs/adapter/bun/index.js" + }, + "./nextjs": { + "types": "./dist/types/adapter/nextjs/index.d.ts", + "import": "./dist/adapter/nextjs/index.js", + "require": "./dist/cjs/adapter/nextjs/index.js" + }, + "./aws-lambda": { + "types": "./dist/types/adapter/aws-lambda/index.d.ts", + "import": "./dist/adapter/aws-lambda/index.js", + "require": "./dist/cjs/adapter/aws-lambda/index.js" + }, + "./vercel": { + "types": "./dist/types/adapter/vercel/index.d.ts", + "import": "./dist/adapter/vercel/index.js", + "require": "./dist/cjs/adapter/vercel/index.js" + }, + "./lambda-edge": { + "types": "./dist/types/adapter/lambda-edge/index.d.ts", + "import": "./dist/adapter/lambda-edge/index.js", + "require": "./dist/cjs/adapter/lambda-edge/index.js" + }, + "./testing": { + "types": "./dist/types/helper/testing/index.d.ts", + "import": "./dist/helper/testing/index.js", + "require": "./dist/cjs/helper/testing/index.js" + }, + "./dev": { + "types": "./dist/types/helper/dev/index.d.ts", + "import": "./dist/helper/dev/index.js", + "require": "./dist/cjs/helper/dev/index.js" + } + }, + "typesVersions": { + "*": { + "types": [ + "./dist/types/types" + ], + "hono-base": [ + "./dist/types/hono-base" + ], + "tiny": [ + "./dist/types/preset/tiny" + ], + "quick": [ + "./dist/types/preset/quick" + ], + "http-exception": [ + "./dist/types/http-exception" + ], + "basic-auth": [ + "./dist/types/middleware/basic-auth" + ], + "bearer-auth": [ + "./dist/types/middleware/bearer-auth" + ], + "body-limit": [ + "./dist/types/middleware/body-limit" + ], + "cache": [ + "./dist/types/middleware/cache" + ], + "cookie": [ + "./dist/types/helper/cookie" + ], + "compress": [ + "./dist/types/middleware/compress" + ], + "cors": [ + "./dist/types/middleware/cors" + ], + "csrf": [ + "./dist/types/middleware/csrf" + ], + "etag": [ + "./dist/types/middleware/etag" + ], + "html": [ + "./dist/types/helper/html" + ], + "css": [ + "./dist/types/helper/css" + ], + "jsx": [ + "./dist/types/jsx" + ], + "jsx/jsx-runtime": [ + "./dist/types/jsx/jsx-runtime.d.ts" + ], + "jsx/jsx-dev-runtime": [ + "./dist/types/jsx/jsx-dev-runtime.d.ts" + ], + "jsx/streaming": [ + "./dist/types/jsx/streaming.d.ts" + ], + "jsx-renderer": [ + "./dist/types/middleware/jsx-renderer" + ], + "jwt": [ + "./dist/types/middleware/jwt" + ], + "timing": [ + "./dist/types/middleware/timing" + ], + "logger": [ + "./dist/types/middleware/logger" + ], + "powered-by": [ + "./dist/types/middleware/powered-by" + ], + "pretty-json": [ + "./dist/types/middleware/pretty-json" + ], + "streaming": [ + "./dist/types/helper/streaming" + ], + "secure-headers": [ + "./dist/types/middleware/secure-headers" + ], + "validator": [ + "./dist/types/validator/index.d.ts" + ], + "router": [ + "./dist/types/router.d.ts" + ], + "router/reg-exp-router": [ + "./dist/types/router/reg-exp-router/router.d.ts" + ], + "router/smart-router": [ + "./dist/types/router/smart-router/router.d.ts" + ], + "router/trie-router": [ + "./dist/types/router/trie-router/router.d.ts" + ], + "router/pattern-router": [ + "./dist/types/router/pattern-router/router.d.ts" + ], + "router/linear-router": [ + "./dist/types/router/linear-router/router.d.ts" + ], + "utils/jwt": [ + "./dist/types/utils/jwt/index.d.ts" + ], + "utils/*": [ + "./dist/types/utils/*" + ], + "client": [ + "./dist/types/client/index.d.ts" + ], + "adapter": [ + "./dist/types/helper/adapter/index.d.ts" + ], + "factory": [ + "./dist/types/helper/factory/index.d.ts" + ], + "cloudflare-workers": [ + "./dist/types/adapter/cloudflare-workers" + ], + "cloudflare-pages": [ + "./dist/types/adapter/cloudflare-pages" + ], + "deno": [ + "./dist/types/adapter/deno" + ], + "bun": [ + "./dist/types/adapter/bun" + ], + "nextjs": [ + "./dist/types/adapter/nextjs" + ], + "aws-lambda": [ + "./dist/types/adapter/aws-lambda" + ], + "vercel": [ + "./dist/types/adapter/vercel" + ], + "lambda-edge": [ + "./dist/types/adapter/lambda-edge" + ], + "testing": [ + "./dist/types/helper/testing" + ], + "dev": [ + "./dist/types/helper/dev" + ] + } + }, + "author": "Yusuke Wada (https://github.com/yusukebe)", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/honojs/hono.git" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org" + }, + "homepage": "https://hono.dev", + "keywords": [ + "hono", + "web", + "app", + "http", + "application", + "framework", + "router", + "cloudflare", + "workers", + "fastly", + "compute@edge", + "deno", + "bun", + "lagon", + "lambda", + "nodejs" + ], + "devDependencies": { + "@cloudflare/workers-types": "^4.20231121.0", + "@hono/eslint-config": "^0.0.3", + "@hono/node-server": "^1.3.3", + "@types/crypto-js": "^4.1.1", + "@types/glob": "^8.0.0", + "@types/jsdom": "^21.1.4", + "@types/node": "^20.8.2", + "@types/node-fetch": "^2.6.2", + "@types/supertest": "^2.0.12", + "@vitest/coverage-v8": "^1.1.0", + "arg": "^5.0.2", + "crypto-js": "^4.1.1", + "denoify": "^1.6.6", + "esbuild": "^0.15.12", + "eslint": "^8.55.0", + "form-data": "^4.0.0", + "jsdom": "^22.1.0", + "msw": "^1.0.0", + "node-fetch": "2", + "np": "^7.7.0", + "prettier": "^2.6.2", + "publint": "^0.1.8", + "rimraf": "^3.0.2", + "start-server-and-test": "^1.15.2", + "supertest": "^6.3.3", + "tsx": "^3.11.0", + "typescript": "^5.3.3", + "vite-plugin-fastly-js-compute": "^0.4.2", + "vitest": "^1.1.0", + "wrangler": "3.17.1", + "zod": "^3.20.2" + }, + "engines": { + "node": ">=16.0.0" + } + } + \ No newline at end of file diff --git a/src/middleware/body-limit/index.ts b/src/middleware/body-limit/index.ts index e04786799..ff2f8836a 100644 --- a/src/middleware/body-limit/index.ts +++ b/src/middleware/body-limit/index.ts @@ -80,8 +80,35 @@ export const bodyLimit = ( return async function bodylimit(c: Context, next: () => Promise) { if (allowMethods.includes(c.req.method.toUpperCase())) { const req = c.req.raw.clone() - const blob = await req.blob() - const bodySize = blob.size + let cachedBody = null; + + const cacheRequestBody = async () => { + const reader = req.body.getReader(); + const chunks = []; + + for (;;) { + const { done, value } = await reader.read(); + + if (done) break; + + chunks.push(value); + } + + const body = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0)); + let offset = 0; + + for (const chunk of chunks) { + body.set(chunk, offset); + offset += chunk.length; + } + + cachedBody = body; + }; + + await cacheRequestBody(); + + const blob = new Blob([cachedBody]); + const bodySize = blob.size; let type: typeof bodyTypes[number] = 'body' const ContentType = req.headers.get('Content-Type')?.trim() ?? '' diff --git a/yarn.lock b/yarn.lock index 02b8a5b26..4ea1eb5cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -484,6 +484,18 @@ magic-string "^0.30.0" regexpu-core "^5.3.2" +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hono/eslint-config@^0.0.3": version "0.0.3" resolved "https://registry.yarnpkg.com/@hono/eslint-config/-/eslint-config-0.0.3.tgz#15978d401c53c5497156f0a80dc2b261e94139c9" @@ -794,6 +806,23 @@ dependencies: any-observable "^0.3.0" +"@sideway/address@^4.1.4": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -1416,6 +1445,14 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== +axios@^0.27.2: + version "0.27.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -1464,6 +1501,11 @@ blake3-wasm@^2.1.5: resolved "https://registry.yarnpkg.com/blake3-wasm/-/blake3-wasm-2.1.5.tgz#b22dbb84bc9419ed0159caa76af4b1b132e6ba52" integrity sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g== +bluebird@3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + boxen@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" @@ -1687,6 +1729,11 @@ check-error@^1.0.3: dependencies: get-func-name "^2.0.2" +check-more-types@2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" + integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA== + chokidar@^3.4.2, chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -1975,7 +2022,7 @@ date-fns@^1.27.2: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== -debug@4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2185,6 +2232,11 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA== +duplexer@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" @@ -2700,6 +2752,19 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-stream@=3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -2714,7 +2779,7 @@ evt@2.5.3: run-exclusive "^2.2.19" tsafe "^1.6.5" -execa@^5.0.0: +execa@5.1.1, execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -2880,6 +2945,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== +follow-redirects@^1.14.9: + version "1.15.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" + integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -2922,6 +2992,11 @@ formidable@^2.1.1: once "^1.4.0" qs "^6.11.0" +from@~0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -3935,6 +4010,17 @@ istanbul-reports@^3.1.6: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +joi@^17.7.0: + version "17.12.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.12.0.tgz#a3fb5715f198beb0471cd551dd26792089c308d5" + integrity sha512-HSLsmSmXz+PV9PYoi3p7cgIbj06WnEBNT28n+bbBNcPZXZFqCzzvGqpTBPujx/Z0nh1+KNQPDrNgdmQ8dq0qYw== + dependencies: + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.4" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + js-levenshtein@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" @@ -4050,6 +4136,11 @@ latest-version@^5.1.0: dependencies: package-json "^6.3.0" +lazy-ass@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" + integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -4269,6 +4360,11 @@ map-obj@^4.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== + meow@^8.1.0: version "8.1.2" resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897" @@ -4417,7 +4513,7 @@ minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -minimist@^1.2.6: +minimist@^1.2.6, minimist@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -5055,6 +5151,13 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== +pause-stream@0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== + dependencies: + through "~2.3" + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -5126,6 +5229,13 @@ printable-characters@^1.0.42: resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8" integrity sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ== +ps-tree@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" + integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== + dependencies: + event-stream "=3.3.4" + psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -5495,6 +5605,13 @@ rxjs@^7.5.5: dependencies: tslib "^2.1.0" +rxjs@^7.8.0: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + sade@^1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" @@ -5727,6 +5844,13 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA== + dependencies: + through "2" + split@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" @@ -5747,6 +5871,20 @@ stacktracey@^2.1.8: as-table "^1.0.36" get-source "^2.0.12" +start-server-and-test@^1.15.2: + version "1.15.5" + resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.15.5.tgz#5c9103bd87c06678fc62658fbe97d09501714011" + integrity sha512-o3EmkX0++GV+qsvIJ/OKWm3w91fD8uS/bPQVPrh/7loaxkpXSuAIHdnmN/P/regQK9eNAK76aBJcHt+OSTk+nA== + dependencies: + arg "^5.0.2" + bluebird "3.7.2" + check-more-types "2.24.0" + debug "4.3.4" + execa "5.1.1" + lazy-ass "1.6.0" + ps-tree "1.2.0" + wait-on "7.0.1" + std-env@^3.5.0: version "3.6.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.6.0.tgz#94807562bddc68fa90f2e02c5fd5b6865bb4e98e" @@ -5764,6 +5902,13 @@ stoppable@^1.1.0: resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b" integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw== + dependencies: + duplexer "~0.1.1" + strict-event-emitter@^0.2.4: version "0.2.8" resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.2.8.tgz#b4e768927c67273c14c13d20e19d5e6c934b47ca" @@ -6018,7 +6163,7 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -through@2, through@^2.3.6, through@^2.3.8: +through@2, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -6467,6 +6612,17 @@ w3c-xmlserializer@^4.0.0: dependencies: xml-name-validator "^4.0.0" +wait-on@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.0.1.tgz#5cff9f8427e94f4deacbc2762e6b0a489b19eae9" + integrity sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog== + dependencies: + axios "^0.27.2" + joi "^17.7.0" + lodash "^4.17.21" + minimist "^1.2.7" + rxjs "^7.8.0" + wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" From 0790c516aa7c8ef1936fc4c8e3f5a5bdf48e1e0e Mon Sep 17 00:00:00 2001 From: EdamAme <121654029+EdamAme-x@users.noreply.github.com> Date: Sun, 28 Jan 2024 01:25:39 +0000 Subject: [PATCH 10/14] fix --- src/middleware/body-limit/index.test.ts | 14 ++++++++++++++ src/middleware/body-limit/index.ts | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/middleware/body-limit/index.test.ts b/src/middleware/body-limit/index.test.ts index 35669c81f..789e4723f 100644 --- a/src/middleware/body-limit/index.test.ts +++ b/src/middleware/body-limit/index.test.ts @@ -267,6 +267,20 @@ describe('bodyLimit by Middleware', () => { expect(await res.text()).toBe('no') }) + it('enum limit with custom handler', async () => { + const res = await app.request('/enum-limit-custom', { + method: 'POST', + headers: new Headers({ + 'Content-Type': 'application/json, text/plain', + }), + body: JSON.stringify(exampleJSON2), + }) + + expect(res).not.toBeNull() + expect(res.status).toBe(413) + expect(await res.text()).toBe('no') + }) + it('Unit test', () => { let beforeSize = 1 / 1024 diff --git a/src/middleware/body-limit/index.ts b/src/middleware/body-limit/index.ts index ff2f8836a..c9ae4dcec 100644 --- a/src/middleware/body-limit/index.ts +++ b/src/middleware/body-limit/index.ts @@ -79,7 +79,7 @@ export const bodyLimit = ( return async function bodylimit(c: Context, next: () => Promise) { if (allowMethods.includes(c.req.method.toUpperCase())) { - const req = c.req.raw.clone() + const req = c.req.raw let cachedBody = null; const cacheRequestBody = async () => { From da6226d3f27e5b3a16b7095940907f6e9f6174f0 Mon Sep 17 00:00:00 2001 From: EdamAme <121654029+EdamAme-x@users.noreply.github.com> Date: Sun, 28 Jan 2024 01:40:38 +0000 Subject: [PATCH 11/14] fix use stream --- src/middleware/body-limit/index.ts | 48 ++++++++++++++---------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/middleware/body-limit/index.ts b/src/middleware/body-limit/index.ts index c9ae4dcec..0ec42a8d9 100644 --- a/src/middleware/body-limit/index.ts +++ b/src/middleware/body-limit/index.ts @@ -8,11 +8,13 @@ type bodyLimitOptions = { handler?: (c: Context) => Response }[] +type bodyLimitOption = bodyLimitOptions[number]; + type bodyLimitObject = { - body?: bodyLimitOptions[number] - json?: bodyLimitOptions[number] - form?: bodyLimitOptions[number] - text?: bodyLimitOptions[number] + body?: bodyLimitOption + json?: bodyLimitOption + form?: bodyLimitOption + text?: bodyLimitOption } const defaultOptions: bodyLimitOptions = bodyTypes.map((bodyType) => { @@ -73,42 +75,36 @@ const deleteSameType = (options: bodyLimitOptions): bodyLimitObject => { * ``` */ export const bodyLimit = ( - options: bodyLimitOptions | bodyLimitOptions[number] = defaultOptions + options: bodyLimitOptions | bodyLimitOption = defaultOptions ): MiddlewareHandler => { const limitOptions: bodyLimitObject = deleteSameType([...defaultOptions, ...[options].flat()]) return async function bodylimit(c: Context, next: () => Promise) { if (allowMethods.includes(c.req.method.toUpperCase())) { const req = c.req.raw - let cachedBody = null; - - const cacheRequestBody = async () => { - const reader = req.body.getReader(); - const chunks = []; - for (;;) { - const { done, value } = await reader.read(); + const reader = req.body.getReader() + const chunks = [] - if (done) break; + for (;;) { + const { done, value } = await reader.read() - chunks.push(value); - } + if (done) break - const body = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0)); - let offset = 0; + chunks.push(value) + } - for (const chunk of chunks) { - body.set(chunk, offset); - offset += chunk.length; - } + const body = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0)) + let offset = 0 - cachedBody = body; - }; + for (const chunk of chunks) { + body.set(chunk, offset) + offset += chunk.length + } - await cacheRequestBody(); + c.req.bodyCache.arrayBuffer = body - const blob = new Blob([cachedBody]); - const bodySize = blob.size; + const bodySize = body.length let type: typeof bodyTypes[number] = 'body' const ContentType = req.headers.get('Content-Type')?.trim() ?? '' From 49f1554ca0010c391255b7317ab064475e3eafdc Mon Sep 17 00:00:00 2001 From: EdamAme <121654029+EdamAme-x@users.noreply.github.com> Date: Sun, 28 Jan 2024 01:43:07 +0000 Subject: [PATCH 12/14] chore: resolve --- package.json | 82 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index f63a55ed8..f038beb39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hono", - "version": "3.12.1", + "version": "4.0.0-rc.2", "description": "Ultrafast web framework for the Edges", "main": "dist/cjs/index.js", "type": "module", @@ -10,21 +10,21 @@ "dist" ], "scripts": { - "test": "tsc --noEmit && vitest --run", - "test:deno": "env NAME=Deno deno test --allow-read --allow-env runtime_tests/deno && deno test --no-lock -c runtime_tests/deno-jsx/deno.precompile.json runtime_tests/deno-jsx && deno test --no-lock -c runtime_tests/deno-jsx/deno.react-jsx.json runtime_tests/deno-jsx", - "test:bun": "env NAME=Bun bun test --jsx-import-source ../../src/jsx runtime_tests/bun/index.test.tsx", + "test": "tsc --noEmit && vitest --run && vitest -c .vitest.config/jsx-runtime-default.ts --run && vitest -c .vitest.config/jsx-runtime-dom.ts --run", + "test:watch": "vitest --watch", + "test:deno": "deno test --allow-read --allow-env --allow-write -c runtime_tests/deno/deno.json runtime_tests/deno && deno test --no-lock -c runtime_tests/deno-jsx/deno.precompile.json runtime_tests/deno-jsx && deno test --no-lock -c runtime_tests/deno-jsx/deno.react-jsx.json runtime_tests/deno-jsx", + "test:bun": "bun test --jsx-import-source ../../src/jsx runtime_tests/bun/index.test.tsx", "test:fastly": "vitest --run --config ./runtime_tests/fastly/vitest.config.ts", - "test:lagon": "start-server-and-test \"lagon dev runtime_tests/lagon/index.ts -e runtime_tests/lagon/.env.lagon\" http://127.0.0.1:1234 \"yarn vitest --run runtime_tests/lagon/index.test.ts --config runtime_tests/lagon/vitest.config.ts\"", - "test:node": "env NAME=Node vitest --run --config ./runtime_tests/node/vitest.config.ts", + "test:node": "vitest --run --config ./runtime_tests/node/vitest.config.ts", "test:wrangler": "vitest --run --config ./runtime_tests/wrangler/vitest.config.ts", - "test:lambda": "env NAME=Node vitest --run --config ./runtime_tests/lambda/vitest.config.ts", - "test:lambda-edge": "env NAME=Node vitest --run --config ./runtime_tests/lambda-edge/vitest.config.ts", - "test:all": "yarn test && yarn test:deno && yarn test:bun && yarn test:fastly && yarn test:lagon && yarn test:node && yarn test:wrangler && yarn test:lambda && yarn test:lambda-edge", - "lint": "eslint --ext js,ts src runtime_tests", - "lint:fix": "eslint --ext js,ts src runtime_tests --fix", - "format": "prettier --check 'src/**/*.{js,ts}' 'runtime_tests/**/*.{js,ts}'", - "format:fix": "prettier --write 'src/**/*.{js,ts}' 'runtime_tests/**/*.{js,ts}'", - "denoify": "rimraf deno_dist && denoify && rimraf 'deno_dist/**/*.test.{ts,tsx}'", + "test:lambda": "vitest --run --config ./runtime_tests/lambda/vitest.config.ts", + "test:lambda-edge": "vitest --run --config ./runtime_tests/lambda-edge/vitest.config.ts", + "test:all": "yarn test && yarn test:deno && yarn test:bun && yarn test:fastly && yarn test:node && yarn test:wrangler && yarn test:lambda && yarn test:lambda-edge", + "lint": "eslint --ext js,ts,tsx src runtime_tests", + "lint:fix": "eslint --ext js,ts,tsx src runtime_tests --fix", + "format": "prettier --check \"src/**/*.{js,ts,tsx}\" \"runtime_tests/**/*.{js,ts,tsx}\"", + "format:fix": "prettier --write \"src/**/*.{js,ts,tsx}\" \"runtime_tests/**/*.{js,ts,tsx}\"", + "denoify": "rimraf deno_dist && denoify && rimraf \"deno_dist/**/*.test.{ts,tsx}\"", "copy:package.cjs.json": "cp ./package.cjs.json ./dist/cjs/package.json && cp ./package.cjs.json ./dist/types/package.json ", "build": "rimraf dist && tsx ./build.ts && yarn copy:package.cjs.json", "postbuild": "publint", @@ -89,6 +89,11 @@ "import": "./dist/helper/cookie/index.js", "require": "./dist/cjs/helper/cookie/index.js" }, + "./accepts": { + "types": "./dist/types/helper/accepts/index.d.ts", + "import": "./dist/helper/accepts/index.js", + "require": "./dist/cjs/helper/accepts/index.js" + }, "./compress": { "types": "./dist/types/middleware/compress/index.d.ts", "import": "./dist/middleware/compress/index.js", @@ -144,6 +149,26 @@ "import": "./dist/middleware/jsx-renderer/index.js", "require": "./dist/cjs/middleware/jsx-renderer/index.js" }, + "./jsx/dom": { + "types": "./dist/types/jsx/dom/index.d.ts", + "import": "./dist/jsx/dom/index.js", + "require": "./dist/cjs/jsx/dom/index.js" + }, + "./jsx/dom/jsx-dev-runtime": { + "types": "./dist/types/jsx/dom/jsx-dev-runtime.d.ts", + "import": "./dist/jsx/dom/jsx-dev-runtime.js", + "require": "./dist/cjs/jsx/dom/jsx-dev-runtime.js" + }, + "./jsx/dom/jsx-runtime": { + "types": "./dist/types/jsx/dom/jsx-runtime.d.ts", + "import": "./dist/jsx/dom/jsx-runtime.js", + "require": "./dist/cjs/jsx/dom/jsx-runtime.js" + }, + "./jsx/dom/css": { + "types": "./dist/types/jsx/dom/css.d.ts", + "import": "./dist/jsx/dom/css.js", + "require": "./dist/cjs/jsx/dom/css.js" + }, "./jwt": { "types": "./dist/types/middleware/jwt/index.d.ts", "import": "./dist/middleware/jwt/index.js", @@ -174,6 +199,11 @@ "import": "./dist/middleware/secure-headers/index.js", "require": "./dist/cjs/middleware/secure-headers/index.js" }, + "./ssg": { + "types": "./dist/types/helper/ssg/index.d.ts", + "import": "./dist/helper/ssg/index.js", + "require": "./dist/cjs/helper/ssg/index.js" + }, "./streaming": { "types": "./dist/types/helper/streaming/index.d.ts", "import": "./dist/helper/streaming/index.js", @@ -259,11 +289,6 @@ "import": "./dist/adapter/bun/index.js", "require": "./dist/cjs/adapter/bun/index.js" }, - "./nextjs": { - "types": "./dist/types/adapter/nextjs/index.d.ts", - "import": "./dist/adapter/nextjs/index.js", - "require": "./dist/cjs/adapter/nextjs/index.js" - }, "./aws-lambda": { "types": "./dist/types/adapter/aws-lambda/index.d.ts", "import": "./dist/adapter/aws-lambda/index.js", @@ -274,6 +299,11 @@ "import": "./dist/adapter/vercel/index.js", "require": "./dist/cjs/adapter/vercel/index.js" }, + "./netlify": { + "types": "./dist/types/adapter/netlify/index.d.ts", + "import": "./dist/adapter/netlify/index.js", + "require": "./dist/cjs/adapter/netlify/index.js" + }, "./lambda-edge": { "types": "./dist/types/adapter/lambda-edge/index.d.ts", "import": "./dist/adapter/lambda-edge/index.js", @@ -322,6 +352,9 @@ "cookie": [ "./dist/types/helper/cookie" ], + "accepts": [ + "./dist/types/helper/accepts" + ], "compress": [ "./dist/types/middleware/compress" ], @@ -355,6 +388,12 @@ "jsx-renderer": [ "./dist/types/middleware/jsx-renderer" ], + "jsx/dom": [ + "./dist/types/jsx/dom" + ], + "jsx/dom/css": [ + "./dist/types/jsx/dom/css.d.ts" + ], "jwt": [ "./dist/types/middleware/jwt" ], @@ -373,6 +412,9 @@ "streaming": [ "./dist/types/helper/streaming" ], + "ssg": [ + "./dist/types/helper/ssg" + ], "secure-headers": [ "./dist/types/middleware/secure-headers" ], @@ -468,7 +510,6 @@ "compute@edge", "deno", "bun", - "lagon", "lambda", "nodejs" ], @@ -496,7 +537,6 @@ "prettier": "^2.6.2", "publint": "^0.1.8", "rimraf": "^3.0.2", - "start-server-and-test": "^1.15.2", "supertest": "^6.3.3", "tsx": "^3.11.0", "typescript": "^5.3.3", From f60d74cfda24e80894493e410f57552a2c907aff Mon Sep 17 00:00:00 2001 From: EdamAme <121654029+EdamAme-x@users.noreply.github.com> Date: Sun, 28 Jan 2024 02:06:58 +0000 Subject: [PATCH 13/14] fix --- src/middleware/body-limit/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middleware/body-limit/index.ts b/src/middleware/body-limit/index.ts index 0ec42a8d9..7143b25e1 100644 --- a/src/middleware/body-limit/index.ts +++ b/src/middleware/body-limit/index.ts @@ -8,7 +8,7 @@ type bodyLimitOptions = { handler?: (c: Context) => Response }[] -type bodyLimitOption = bodyLimitOptions[number]; +type bodyLimitOption = bodyLimitOptions[number] type bodyLimitObject = { body?: bodyLimitOption From fa1c8ae99c284da7da83aaec7b77aa8d1e660435 Mon Sep 17 00:00:00 2001 From: EdamAme <121654029+EdamAme-x@users.noreply.github.com> Date: Sun, 28 Jan 2024 02:23:08 +0000 Subject: [PATCH 14/14] chore: denoify & format --- deno_dist/middleware/body-limit/index.ts | 103 +++++++++++++-------- src/middleware/body-limit/index.ts | 108 ++++++++++++----------- 2 files changed, 119 insertions(+), 92 deletions(-) diff --git a/deno_dist/middleware/body-limit/index.ts b/deno_dist/middleware/body-limit/index.ts index 878b0d06c..d649513b2 100644 --- a/deno_dist/middleware/body-limit/index.ts +++ b/deno_dist/middleware/body-limit/index.ts @@ -8,11 +8,13 @@ type bodyLimitOptions = { handler?: (c: Context) => Response }[] +type bodyLimitOption = bodyLimitOptions[number] + type bodyLimitObject = { - body?: bodyLimitOptions[number] - json?: bodyLimitOptions[number] - form?: bodyLimitOptions[number] - text?: bodyLimitOptions[number] + body?: bodyLimitOption + json?: bodyLimitOption + form?: bodyLimitOption + text?: bodyLimitOption } const defaultOptions: bodyLimitOptions = bodyTypes.map((bodyType) => { @@ -73,46 +75,69 @@ const deleteSameType = (options: bodyLimitOptions): bodyLimitObject => { * ``` */ export const bodyLimit = ( - options: bodyLimitOptions | bodyLimitOptions[number] = defaultOptions + options: bodyLimitOptions | bodyLimitOption = defaultOptions ): MiddlewareHandler => { const limitOptions: bodyLimitObject = deleteSameType([...defaultOptions, ...[options].flat()]) return async function bodylimit(c: Context, next: () => Promise) { if (allowMethods.includes(c.req.method.toUpperCase())) { - const req = c.req.raw.clone() - const blob = await req.blob() - const bodySize = blob.size - - let type: typeof bodyTypes[number] = 'body' - const ContentType = req.headers.get('Content-Type')?.trim() ?? '' - - if (ContentType.startsWith('text/plain')) { - type = 'text' - } else if (ContentType.startsWith('application/json')) { - type = 'json' - } else if (ContentType.startsWith('application/x-www-form-urlencoded')) { - type = 'form' - } - - const limitOption = limitOptions[type] - const bodyLimitOption = limitOptions['body'] - - if ( - limitOption && - limitOption.maxSize && - limitOption.handler && - !isNaN(limitOption.maxSize) && - bodySize > limitOption.maxSize - ) { - return limitOption.handler(c) - } else if ( - bodyLimitOption && - bodyLimitOption.maxSize && - bodyLimitOption.handler && - !isNaN(bodyLimitOption.maxSize) && - bodySize > bodyLimitOption.maxSize - ) { - return bodyLimitOption.handler(c) + const req = c.req.raw + + if (req.body) { + const reader = req.body.getReader() + const chunks = [] + + for (;;) { + const { done, value } = await reader.read() + + if (done) break + + chunks.push(value) + } + + const body = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0)) + let offset = 0 + + for (const chunk of chunks) { + body.set(chunk, offset) + offset += chunk.length + } + + c.req.bodyCache.arrayBuffer = body + + const bodySize = body.length + + let type: typeof bodyTypes[number] = 'body' + const ContentType = req.headers.get('Content-Type')?.trim() ?? '' + + if (ContentType.startsWith('text/plain')) { + type = 'text' + } else if (ContentType.startsWith('application/json')) { + type = 'json' + } else if (ContentType.startsWith('application/x-www-form-urlencoded')) { + type = 'form' + } + + const limitOption = limitOptions[type] + const bodyLimitOption = limitOptions['body'] + + if ( + limitOption && + limitOption.maxSize && + limitOption.handler && + !isNaN(limitOption.maxSize) && + bodySize > limitOption.maxSize + ) { + return limitOption.handler(c) + } else if ( + bodyLimitOption && + bodyLimitOption.maxSize && + bodyLimitOption.handler && + !isNaN(bodyLimitOption.maxSize) && + bodySize > bodyLimitOption.maxSize + ) { + return bodyLimitOption.handler(c) + } } } diff --git a/src/middleware/body-limit/index.ts b/src/middleware/body-limit/index.ts index 7143b25e1..9381ea90d 100644 --- a/src/middleware/body-limit/index.ts +++ b/src/middleware/body-limit/index.ts @@ -83,59 +83,61 @@ export const bodyLimit = ( if (allowMethods.includes(c.req.method.toUpperCase())) { const req = c.req.raw - const reader = req.body.getReader() - const chunks = [] - - for (;;) { - const { done, value } = await reader.read() - - if (done) break - - chunks.push(value) - } - - const body = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0)) - let offset = 0 - - for (const chunk of chunks) { - body.set(chunk, offset) - offset += chunk.length - } - - c.req.bodyCache.arrayBuffer = body - - const bodySize = body.length - - let type: typeof bodyTypes[number] = 'body' - const ContentType = req.headers.get('Content-Type')?.trim() ?? '' - - if (ContentType.startsWith('text/plain')) { - type = 'text' - } else if (ContentType.startsWith('application/json')) { - type = 'json' - } else if (ContentType.startsWith('application/x-www-form-urlencoded')) { - type = 'form' - } - - const limitOption = limitOptions[type] - const bodyLimitOption = limitOptions['body'] - - if ( - limitOption && - limitOption.maxSize && - limitOption.handler && - !isNaN(limitOption.maxSize) && - bodySize > limitOption.maxSize - ) { - return limitOption.handler(c) - } else if ( - bodyLimitOption && - bodyLimitOption.maxSize && - bodyLimitOption.handler && - !isNaN(bodyLimitOption.maxSize) && - bodySize > bodyLimitOption.maxSize - ) { - return bodyLimitOption.handler(c) + if (req.body) { + const reader = req.body.getReader() + const chunks = [] + + for (;;) { + const { done, value } = await reader.read() + + if (done) break + + chunks.push(value) + } + + const body = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0)) + let offset = 0 + + for (const chunk of chunks) { + body.set(chunk, offset) + offset += chunk.length + } + + c.req.bodyCache.arrayBuffer = body + + const bodySize = body.length + + let type: typeof bodyTypes[number] = 'body' + const ContentType = req.headers.get('Content-Type')?.trim() ?? '' + + if (ContentType.startsWith('text/plain')) { + type = 'text' + } else if (ContentType.startsWith('application/json')) { + type = 'json' + } else if (ContentType.startsWith('application/x-www-form-urlencoded')) { + type = 'form' + } + + const limitOption = limitOptions[type] + const bodyLimitOption = limitOptions['body'] + + if ( + limitOption && + limitOption.maxSize && + limitOption.handler && + !isNaN(limitOption.maxSize) && + bodySize > limitOption.maxSize + ) { + return limitOption.handler(c) + } else if ( + bodyLimitOption && + bodyLimitOption.maxSize && + bodyLimitOption.handler && + !isNaN(bodyLimitOption.maxSize) && + bodySize > bodyLimitOption.maxSize + ) { + return bodyLimitOption.handler(c) + } } }