mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-19 15:10:58 +00:00
feat(nitro): add support for lambda v2 payload format (#3070)
Co-authored-by: Pooya Parsa <pyapar@gmail.com>
This commit is contained in:
parent
68a227af03
commit
614e87e9f0
@ -24,6 +24,10 @@ Or directly use the `NITRO_PRESET` environment variable when running `nuxt build
|
|||||||
NITRO_PRESET=lambda npx nuxt build
|
NITRO_PRESET=lambda npx nuxt build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
::alert
|
||||||
|
AWS Lambda [defaults to payload version v2](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html). This Nitro preset supports both v1 and v2 payloads.
|
||||||
|
::
|
||||||
|
|
||||||
### Entrypoint
|
### Entrypoint
|
||||||
|
|
||||||
When running `nuxt build` with the Lambda preset, the result will be an entry point that exports a handler function that responds to an event and returns a response.
|
When running `nuxt build` with the Lambda preset, the result will be an entry point that exports a handler function that responds to an event and returns a response.
|
||||||
@ -36,5 +40,5 @@ It can be used programmatically or as part of a deployment.
|
|||||||
import { handler } from './.output/server'
|
import { handler } from './.output/server'
|
||||||
|
|
||||||
// Use programmatically
|
// Use programmatically
|
||||||
const { statusCode, headers, body } = handler({ path: '/' })
|
const { statusCode, headers, body } = handler({ rawPath: '/' })
|
||||||
```
|
```
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/schema": "3.0.0",
|
"@nuxt/schema": "3.0.0",
|
||||||
|
"@types/aws-lambda": "^8.10.92",
|
||||||
"@types/fs-extra": "^9.0.13",
|
"@types/fs-extra": "^9.0.13",
|
||||||
"@types/http-proxy": "^1.17.8",
|
"@types/http-proxy": "^1.17.8",
|
||||||
"@types/node-fetch": "^3.0.2",
|
"@types/node-fetch": "^3.0.2",
|
||||||
|
@ -1,21 +1,34 @@
|
|||||||
|
import type { APIGatewayProxyEvent, APIGatewayProxyEventHeaders, APIGatewayProxyEventV2, Context } from 'aws-lambda'
|
||||||
import '#polyfill'
|
import '#polyfill'
|
||||||
import { withQuery } from 'ufo'
|
import { withQuery } from 'ufo'
|
||||||
|
import type { HeadersObject } from 'unenv/runtime/_internal/types'
|
||||||
import { localCall } from '../server'
|
import { localCall } from '../server'
|
||||||
|
|
||||||
export async function handler (event, context) {
|
export const handler = async function handler (event: APIGatewayProxyEvent & APIGatewayProxyEventV2, context: Context) {
|
||||||
|
const url = withQuery(event.path || event.rawPath, event.queryStringParameters)
|
||||||
|
const method = event.httpMethod || event.requestContext?.http?.method || 'get'
|
||||||
|
|
||||||
const r = await localCall({
|
const r = await localCall({
|
||||||
event,
|
event,
|
||||||
url: withQuery(event.path, event.queryStringParameters),
|
url,
|
||||||
context,
|
context,
|
||||||
headers: event.headers,
|
headers: normalizeIncomingHeaders(event.headers),
|
||||||
method: event.httpMethod,
|
method,
|
||||||
query: event.queryStringParameters,
|
query: event.queryStringParameters,
|
||||||
body: event.body // TODO: handle event.isBase64Encoded
|
body: event.body // TODO: handle event.isBase64Encoded
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: r.status,
|
statusCode: r.status,
|
||||||
headers: r.headers,
|
headers: normalizeOutgoingHeaders(r.headers),
|
||||||
body: r.body.toString()
|
body: r.body.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeIncomingHeaders (headers: APIGatewayProxyEventHeaders) {
|
||||||
|
return Object.fromEntries(Object.entries(headers).map(([key, value]) => [key.toLowerCase(), value as string]))
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeOutgoingHeaders (headers: HeadersObject) {
|
||||||
|
return Object.fromEntries(Object.entries(headers).map(([k, v]) => [k, Array.isArray(v) ? v.join(',') : v]))
|
||||||
|
}
|
||||||
|
@ -1,19 +1,50 @@
|
|||||||
import { resolve } from 'pathe'
|
import { resolve } from 'pathe'
|
||||||
import { describe } from 'vitest'
|
import { describe } from 'vitest'
|
||||||
|
import type { APIGatewayProxyEvent, APIGatewayProxyEventV2 } from 'aws-lambda'
|
||||||
import { setupTest, testNitroBehavior, importModule } from './_tests'
|
import { setupTest, testNitroBehavior, importModule } from './_tests'
|
||||||
|
|
||||||
describe('nitro:preset:lambda', () => {
|
describe('nitro:preset:lambda', () => {
|
||||||
const ctx = setupTest('lambda')
|
const ctx = setupTest('lambda')
|
||||||
|
// Lambda v1 paylod
|
||||||
testNitroBehavior(ctx, async () => {
|
testNitroBehavior(ctx, async () => {
|
||||||
const { handler } = await importModule(resolve(ctx.outDir, 'server/index.mjs'))
|
const { handler } = await importModule(resolve(ctx.outDir, 'server/index.mjs'))
|
||||||
return async ({ url: rawRelativeUrl, headers, method, body }) => {
|
return async ({ url: rawRelativeUrl, headers, method, body }) => {
|
||||||
// creating new URL object to parse query easier
|
// creating new URL object to parse query easier
|
||||||
const url = new URL(`https://example.com${rawRelativeUrl}`)
|
const url = new URL(`https://example.com${rawRelativeUrl}`)
|
||||||
const queryStringParameters = Object.fromEntries(url.searchParams.entries())
|
const queryStringParameters = Object.fromEntries(url.searchParams.entries())
|
||||||
const event = {
|
const event: Partial<APIGatewayProxyEvent> = {
|
||||||
|
resource: '/my/path',
|
||||||
path: url.pathname,
|
path: url.pathname,
|
||||||
headers: headers || {},
|
headers: headers || {},
|
||||||
method: method || 'GET',
|
httpMethod: method || 'GET',
|
||||||
|
queryStringParameters,
|
||||||
|
body: body || ''
|
||||||
|
}
|
||||||
|
const res = await handler(event)
|
||||||
|
return {
|
||||||
|
data: res.body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Lambda v2 paylod
|
||||||
|
testNitroBehavior(ctx, async () => {
|
||||||
|
const { handler } = await importModule(resolve(ctx.outDir, 'server/index.mjs'))
|
||||||
|
return async ({ url: rawRelativeUrl, headers, method, body }) => {
|
||||||
|
// creating new URL object to parse query easier
|
||||||
|
const url = new URL(`https://example.com${rawRelativeUrl}`)
|
||||||
|
const queryStringParameters = Object.fromEntries(url.searchParams.entries())
|
||||||
|
const event: Partial<APIGatewayProxyEventV2> = {
|
||||||
|
rawPath: url.pathname,
|
||||||
|
headers: headers || {},
|
||||||
|
requestContext: {
|
||||||
|
...Object.fromEntries([['accountId'], ['apiId'], ['domainName'], ['domainPrefix']]),
|
||||||
|
http: {
|
||||||
|
path: url.pathname,
|
||||||
|
protocol: 'http',
|
||||||
|
...Object.fromEntries([['userAgent'], ['sourceIp']]),
|
||||||
|
method: method || 'GET'
|
||||||
|
}
|
||||||
|
},
|
||||||
queryStringParameters,
|
queryStringParameters,
|
||||||
body: body || ''
|
body: body || ''
|
||||||
}
|
}
|
||||||
|
@ -2967,6 +2967,7 @@ __metadata:
|
|||||||
"@rollup/plugin-virtual": ^2.0.3
|
"@rollup/plugin-virtual": ^2.0.3
|
||||||
"@rollup/plugin-wasm": ^5.1.2
|
"@rollup/plugin-wasm": ^5.1.2
|
||||||
"@rollup/pluginutils": ^4.1.2
|
"@rollup/pluginutils": ^4.1.2
|
||||||
|
"@types/aws-lambda": ^8.10.92
|
||||||
"@types/fs-extra": ^9.0.13
|
"@types/fs-extra": ^9.0.13
|
||||||
"@types/http-proxy": ^1.17.8
|
"@types/http-proxy": ^1.17.8
|
||||||
"@types/jsdom": ^16.2.14
|
"@types/jsdom": ^16.2.14
|
||||||
@ -3902,6 +3903,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/aws-lambda@npm:^8.10.92":
|
||||||
|
version: 8.10.92
|
||||||
|
resolution: "@types/aws-lambda@npm:8.10.92"
|
||||||
|
checksum: 71c44d83a1c88aa6dbc920baedfb2d100b8843a3d210c695ccaafb30dfb75f04398b0e5368100022acbf75c55d456c61774242f20dd70915fc63d85430cbcf8a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/babel__core@npm:7.1.14":
|
"@types/babel__core@npm:7.1.14":
|
||||||
version: 7.1.14
|
version: 7.1.14
|
||||||
resolution: "@types/babel__core@npm:7.1.14"
|
resolution: "@types/babel__core@npm:7.1.14"
|
||||||
|
Loading…
Reference in New Issue
Block a user