diff --git a/docs/core/event-handler/api-gateway.md b/docs/core/event-handler/api-gateway.md index ae4a753865..aefbbb1750 100644 --- a/docs/core/event-handler/api-gateway.md +++ b/docs/core/event-handler/api-gateway.md @@ -37,17 +37,5 @@ This is the sample infrastructure for API Gateway and Lambda Function URLs we ar ???+ info "There is no additional permissions or dependencies required to use this utility." -=== "API Gateway SAM Template" - - ```yaml title="AWS Serverless Application Model (SAM) example" - --8<-- "examples/snippets/event-handler/rest/templates/template.yaml" - ``` - -=== "Lambda Function URL SAM Template" - - ```yaml title="AWS Serverless Application Model (SAM) example" - --8<-- "examples/event_handler_lambda_function_url/sam/template.yaml" - ``` - - \ No newline at end of file + diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index d8e836184d..db22c17d8a 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -109,6 +109,23 @@ You can extend every built-in schema to include your own schema, and yet have al --8<-- "examples/snippets/parser/examplePayload.json" ``` +For scenarios where you have a stringiied JSON payload, you can extend the built-in schema using `.transform()` and `.pipe()` method. + +=== "APIGatewayProxyEventSchema" + + ```typescript hl_lines="24-34" + --8<-- "examples/snippets/parser/extendAPIGatewaySchema.ts" + ``` + + 1. parse the `body` inside `transform` method + 2. chain your custom schema to `pipe` operation + +=== "Example Payload for API Gateway Event" + + ```json + --8<-- "examples/snippets/parser/exampleAPIGatewayPayload.json" + ``` + ## Envelopes When trying to parse your payload you might encounter the following situations: diff --git a/examples/snippets/parser/exampleAPIGatewayPayload.json b/examples/snippets/parser/exampleAPIGatewayPayload.json new file mode 100644 index 0000000000..35ae3c9b6c --- /dev/null +++ b/examples/snippets/parser/exampleAPIGatewayPayload.json @@ -0,0 +1,81 @@ +{ + "version": "1.0", + "resource": "/my/path", + "path": "/my/path", + "httpMethod": "GET", + "headers": { + "Header1": "value1", + "Header2": "value2", + "Origin": "https://aws.amazon.com" + }, + "multiValueHeaders": { + "Header1": [ + "value1" + ], + "Header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "parameter1": "value1", + "parameter2": "value" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "id", + "authorizer": { + "claims": null, + "scopes": null + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "192.168.0.1", + "user": null, + "userAgent": "user-agent", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/my/path", + "protocol": "HTTP/1.1", + "requestId": "id=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1583349317135, + "resourceId": null, + "resourcePath": "/my/path", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables": null, + "body": "{\"id\":10876546789,\"description\":\"My order\",\"items\":[{\"id\":1015938732,\"quantity\":1,\"description\":\"item xpto\"}]}", + "isBase64Encoded": false +} diff --git a/examples/snippets/parser/extendAPIGatewaySchema.ts b/examples/snippets/parser/extendAPIGatewaySchema.ts new file mode 100644 index 0000000000..4f7d108ca2 --- /dev/null +++ b/examples/snippets/parser/extendAPIGatewaySchema.ts @@ -0,0 +1,50 @@ +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; +import { Logger } from '@aws-lambda-powertools/logger'; +import { parser } from '@aws-lambda-powertools/parser'; +import { APIGatewayProxyEventSchema } from '@aws-lambda-powertools/parser/schemas/api-gateway'; +import type { Context } from 'aws-lambda'; +import { z } from 'zod'; + +const logger = new Logger(); + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), +}); + +const orderEventSchema = APIGatewayProxyEventSchema.extend({ + body: z + .string() + .transform((str, ctx) => { + try { + return JSON.parse(str); // (1)! + } catch (err) { + ctx.addIssue({ + code: 'custom', + message: 'Invalid JSON', + }); + } + }) + .pipe(orderSchema), // (2)! +}); + +type OrderEvent = z.infer; + +class Lambda implements LambdaInterface { + @parser({ schema: orderEventSchema }) + public async handler(event: OrderEvent, _context: Context): Promise { + for (const item of event.body.items) { + // process OrderItem + logger.info('Processing item', { item }); + } + } +} +const myFunction = new Lambda(); +export const handler = myFunction.handler.bind(myFunction);