mirror of
https://github.com/honojs/hono.git
synced 2024-11-22 11:17:33 +01:00
fix(adapter): handle multi value headers in AWS Lambda (#2494)
* Headers can be undefined on ALB * Delegate headers from multiValueHeaders * Add test * Assert header values * format * Make multiValueHeaders optional so it can be omitted * Avoid Object.entries when undefined * Write tests in runtime_tests
This commit is contained in:
parent
932307efd8
commit
acb56b8d30
@ -139,6 +139,13 @@ describe('AWS Lambda Adapter for Hono', () => {
|
||||
return c.text('Valid Cookies')
|
||||
})
|
||||
|
||||
app.post('/headers', (c) => {
|
||||
if (c.req.header('foo')?.includes('bar')) {
|
||||
return c.json({ message: 'ok' })
|
||||
}
|
||||
return c.json({ message: 'fail' }, 400)
|
||||
})
|
||||
|
||||
const handler = handle(app)
|
||||
|
||||
const testApiGatewayRequestContext = {
|
||||
@ -491,6 +498,100 @@ describe('AWS Lambda Adapter for Hono', () => {
|
||||
])
|
||||
})
|
||||
|
||||
describe('headers', () => {
|
||||
describe('single-value headers', () => {
|
||||
it('Should extract single-value headers and return 200 (ALBProxyEvent)', async () => {
|
||||
const event = {
|
||||
body: '{}',
|
||||
httpMethod: 'POST',
|
||||
isBase64Encoded: false,
|
||||
path: '/headers',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
foo: 'bar',
|
||||
},
|
||||
requestContext: testALBRequestContext,
|
||||
}
|
||||
const apiGatewayResponseV2 = await handler(event)
|
||||
expect(apiGatewayResponseV2.statusCode).toBe(200)
|
||||
})
|
||||
|
||||
it('Should extract single-value headers and return 200 (APIGatewayProxyEvent)', async () => {
|
||||
const apigatewayProxyEvent = {
|
||||
version: '1.0',
|
||||
resource: '/headers',
|
||||
httpMethod: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
foo: 'bar',
|
||||
},
|
||||
path: '/headers',
|
||||
body: null,
|
||||
isBase64Encoded: false,
|
||||
requestContext: testApiGatewayRequestContext,
|
||||
}
|
||||
const apiGatewayResponseV2 = await handler(apigatewayProxyEvent)
|
||||
expect(apiGatewayResponseV2.statusCode).toBe(200)
|
||||
})
|
||||
|
||||
it('Should extract single-value headers and return 200 (APIGatewayProxyEventV2)', async () => {
|
||||
const apigatewayProxyV2Event = {
|
||||
version: '2.0',
|
||||
routeKey: '$default',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
foo: 'bar',
|
||||
},
|
||||
rawPath: '/headers',
|
||||
rawQueryString: '',
|
||||
requestContext: testApiGatewayRequestContextV2,
|
||||
resource: '/headers',
|
||||
body: null,
|
||||
isBase64Encoded: false,
|
||||
}
|
||||
const apiGatewayResponseV2 = await handler(apigatewayProxyV2Event)
|
||||
expect(apiGatewayResponseV2.statusCode).toBe(200)
|
||||
})
|
||||
})
|
||||
|
||||
describe('multi-value headers', () => {
|
||||
it('Should extract multi-value headers and return 200 (ALBProxyEvent)', async () => {
|
||||
const event = {
|
||||
body: '{}',
|
||||
httpMethod: 'POST',
|
||||
isBase64Encoded: false,
|
||||
path: '/headers',
|
||||
multiValueHeaders: {
|
||||
host: ['localhost'],
|
||||
foo: ['bar'],
|
||||
},
|
||||
requestContext: testALBRequestContext,
|
||||
}
|
||||
const apiGatewayResponseV2 = await handler(event)
|
||||
expect(apiGatewayResponseV2.statusCode).toBe(200)
|
||||
})
|
||||
|
||||
it('Should extract multi-value headers and return 200 (APIGatewayProxyEvent)', async () => {
|
||||
const apigatewayProxyEvent = {
|
||||
version: '1.0',
|
||||
resource: '/headers',
|
||||
httpMethod: 'POST',
|
||||
headers: {},
|
||||
multiValueHeaders: {
|
||||
host: ['localhost'],
|
||||
foo: ['bar'],
|
||||
},
|
||||
path: '/headers',
|
||||
body: null,
|
||||
isBase64Encoded: false,
|
||||
requestContext: testApiGatewayRequestContext,
|
||||
}
|
||||
const apiGatewayResponseV2 = await handler(apigatewayProxyEvent)
|
||||
expect(apiGatewayResponseV2.statusCode).toBe(200)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('Should handle a POST request and return a 200 response if cookies match (APIGatewayProxyEvent V1 and V2)', async () => {
|
||||
const apiGatewayEvent = {
|
||||
version: '1.0',
|
||||
|
@ -22,6 +22,7 @@ export interface APIGatewayProxyEventV2 {
|
||||
version: string
|
||||
routeKey: string
|
||||
headers: Record<string, string | undefined>
|
||||
multiValueHeaders?: undefined
|
||||
cookies?: string[]
|
||||
rawPath: string
|
||||
rawQueryString: string
|
||||
@ -63,7 +64,8 @@ export interface APIGatewayProxyEvent {
|
||||
// When calling Lambda through an Application Load Balancer
|
||||
export interface ALBProxyEvent {
|
||||
httpMethod: string
|
||||
headers: Record<string, string | undefined>
|
||||
headers?: Record<string, string | undefined>
|
||||
multiValueHeaders?: Record<string, string[] | undefined>
|
||||
path: string
|
||||
body: string | null
|
||||
isBase64Encoded: boolean
|
||||
@ -198,16 +200,25 @@ const createRequest = (event: LambdaEvent) => {
|
||||
const domainName =
|
||||
event.requestContext && 'domainName' in event.requestContext
|
||||
? event.requestContext.domainName
|
||||
: event.headers['host']
|
||||
: event.headers?.['host'] ?? event.multiValueHeaders?.['host']?.[0]
|
||||
const path = isProxyEventV2(event) ? event.rawPath : event.path
|
||||
const urlPath = `https://${domainName}${path}`
|
||||
const url = queryString ? `${urlPath}?${queryString}` : urlPath
|
||||
|
||||
const headers = new Headers()
|
||||
getCookies(event, headers)
|
||||
for (const [k, v] of Object.entries(event.headers)) {
|
||||
if (v) {
|
||||
headers.set(k, v)
|
||||
if (event.headers) {
|
||||
for (const [k, v] of Object.entries(event.headers)) {
|
||||
if (v) {
|
||||
headers.set(k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (event.multiValueHeaders) {
|
||||
for (const [k, values] of Object.entries(event.multiValueHeaders)) {
|
||||
if (values) {
|
||||
values.forEach((v) => headers.append(k, v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user