Skip to content

Commit fa5f9bf

Browse files
authored
Merge commit from fork
1 parent 3892a6c commit fa5f9bf

4 files changed

Lines changed: 86 additions & 2 deletions

File tree

src/adapter/aws-lambda/handler.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { setCookie } from '../../helper/cookie'
22
import { Hono } from '../../hono'
3+
import { bodyLimit } from '../../middleware/body-limit'
34
import type { LambdaEvent, LatticeProxyEventV2 } from './handler'
45
import {
56
getProcessor,
@@ -297,6 +298,7 @@ describe('EventProcessor.createRequest', () => {
297298
'https://id.execute-api.us-east-1.amazonaws.com/my/path?parameter1=value1&parameter1=value2&parameter2=value'
298299
)
299300
expect(Object.fromEntries(request.headers)).toEqual({
301+
'content-length': '17',
300302
'content-type': 'application/json',
301303
cookie: 'cookie1; cookie2',
302304
header1: 'value1',
@@ -342,6 +344,7 @@ describe('EventProcessor.createRequest', () => {
342344
'https://my-service-a1b2c3.x1y2z3.vpc-lattice-svcs.us-east-1.on.aws/my/path?parameter1=value1&parameter1=value2&parameter2=value'
343345
)
344346
expect(Object.fromEntries(request.headers)).toEqual({
347+
'content-length': '17',
345348
'content-type': 'application/x-www-form-urlencoded',
346349
cookie: 'cookie1=value1; cookie2=value2',
347350
header1: 'value1',
@@ -473,4 +476,34 @@ describe('handle', () => {
473476
expect(result.statusCode).toBe(400)
474477
expect(result.body).toBe('Invalid request')
475478
})
479+
480+
it('Should enforce bodyLimit when the client understates Content-Length', async () => {
481+
const app = new Hono()
482+
app.post(
483+
'/upload',
484+
bodyLimit({ maxSize: 1024, onError: (c) => c.text('too large', 413) }),
485+
async (c) => c.json({ received: (await c.req.text()).length })
486+
)
487+
const handler = handle(app)
488+
489+
const event: LambdaEvent = {
490+
...baseV2Event,
491+
rawPath: '/upload',
492+
headers: { 'content-type': 'text/plain', 'content-length': '1' },
493+
body: 'A'.repeat(10000),
494+
requestContext: {
495+
...baseV2Event.requestContext,
496+
http: {
497+
method: 'POST',
498+
path: '/upload',
499+
protocol: 'HTTP/1.1',
500+
sourceIp: '192.0.2.1',
501+
userAgent: 'agent',
502+
},
503+
},
504+
}
505+
506+
const result = await handler(event)
507+
expect(result.statusCode).toBe(413)
508+
})
476509
})

src/adapter/aws-lambda/handler.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,11 @@ export abstract class EventProcessor<E extends LambdaEvent> {
331331
}
332332

333333
if (event.body) {
334-
requestInit.body = event.isBase64Encoded ? decodeBase64(event.body) : event.body
334+
const body = event.isBase64Encoded
335+
? decodeBase64(event.body)
336+
: new TextEncoder().encode(event.body)
337+
requestInit.body = body
338+
headers.set('content-length', body.length.toString())
335339
}
336340

337341
return new Request(url, requestInit)

src/adapter/lambda-edge/handler.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { describe } from 'vitest'
22
import { setCookie } from '../../helper/cookie'
33
import { Hono } from '../../hono'
4+
import { bodyLimit } from '../../middleware/body-limit'
45
import { encodeBase64 } from '../../utils/encode'
56
import type { Callback, CloudFrontEdgeEvent } from './handler'
67
import { createBody, handle, isContentTypeBinary } from './handler'
@@ -182,4 +183,43 @@ describe('handle', () => {
182183
],
183184
})
184185
})
186+
187+
it('Should enforce bodyLimit when the client understates Content-Length', async () => {
188+
const app = new Hono()
189+
app.post(
190+
'/upload',
191+
bodyLimit({ maxSize: 1024, onError: (c) => c.text('too large', 413) }),
192+
async (c) => c.json({ received: (await c.req.text()).length })
193+
)
194+
const handler = handle(app)
195+
196+
const event: CloudFrontEdgeEvent = {
197+
Records: [
198+
{
199+
cf: {
200+
...cloudFrontEdgeEvent.Records[0].cf,
201+
request: {
202+
...cloudFrontEdgeEvent.Records[0].cf.request,
203+
method: 'POST',
204+
uri: '/upload',
205+
headers: {
206+
host: [{ key: 'Host', value: 'hono.dev' }],
207+
'content-type': [{ key: 'Content-Type', value: 'text/plain' }],
208+
'content-length': [{ key: 'Content-Length', value: '1' }],
209+
},
210+
body: {
211+
inputTruncated: false,
212+
action: 'read-only',
213+
encoding: 'text',
214+
data: 'A'.repeat(10000),
215+
},
216+
},
217+
},
218+
},
219+
],
220+
}
221+
222+
const res = await handler(event)
223+
expect(res.status).toBe('413')
224+
})
185225
})

src/adapter/lambda-edge/handler.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,14 @@ const createRequest = (event: CloudFrontEdgeEvent): Request => {
164164

165165
const requestBody = event.Records[0].cf.request.body
166166
const method = event.Records[0].cf.request.method
167-
const body = createBody(method, requestBody)
167+
const rawBody = createBody(method, requestBody)
168+
169+
let body: string | Uint8Array<ArrayBuffer> | undefined = rawBody
170+
if (rawBody !== undefined) {
171+
const bytes = typeof rawBody === 'string' ? new TextEncoder().encode(rawBody) : rawBody
172+
body = bytes
173+
headers.set('content-length', bytes.length.toString())
174+
}
168175

169176
return new Request(url, {
170177
headers,

0 commit comments

Comments
 (0)