Closed
Description
Expected Behavior
We should be able to generate a test form the API Gateway console that allows the ApiGatewayProxyEventModel to be validated and parsed by Zod.
Current Behavior
When generating a test from the API Gateway console, the value for the sourceIp in requestContext -> identity is "test-invoke-source-ip". Since this value is defined to be an ip here And so test events from the API Gateway console fail with a 502 error because of the resulting Zod ValidationError.
Code snippet
RestApi:
Type: AWS::Serverless::Api
Properties:
StageName: !Ref Environment
Name: !Sub '${ProjectName}-${Environment}-api'
OpenApiVersion: '3.0.1'
TracingEnabled: true
EndpointConfiguration: REGIONAL
Auth:
DefaultAuthorizer: NONE
AddDefaultAuthorizerToCorsPreflight: false
ApiKeyRequired: false
Cors:
AllowMethods: "'DELETE,GET,HEAD,OPTIONS,POST,PUT'"
AllowHeaders: "'*'"
AllowOrigin: "'*'"
MethodSettings:
- HttpMethod: '*'
ResourcePath: '/*'
LoggingLevel: INFO
DataTraceEnabled: true
MetricsEnabled: true
ThrottlingBurstLimit: 500
ThrottlingRateLimit: 1000
AccessLogSetting:
DestinationArn: !GetAtt ApiAccessLogGroup.Arn
Format: >-
{
"status": "$context.status",
"traceId": "$context.xrayTraceId",
"requestId": "$context.requestId",
"requestTime": "$context.requestTime",
"httpMethod": "$context.httpMethod",
"responseLength": "$context.responseLength",
"resourcePath": "$context.resourcePath",
"resourceId": "$context.resourceId",
"sourceIp": "$context.identity.sourceIp",
"userAgent": "$context.identity.userAgent",
"accountId": "$context.identity.accountId",
"caller": "$context.identity.caller",
"user": "$context.identity.user",
"userArn": "$context.identity.userArn"
}
Tags:
APPLI: !Ref ApplicationName
ProjectName: !Ref ProjectName
ENV: !Ref Environment
Owner: !Ref Owner
// Lambda parses input and returns back the metadata field with a 200 status code
UploadFileFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub '${ProjectName}-${Environment}-upload-file'
CodeUri: ../../../dist/packages/backend/upload-file/
CodeSigningConfigArn: !If [IsSandbox, !Ref AWS::NoValue, !Ref SignedCodeSigningConfigArn]
Events:
Api:
Type: Api
Properties:
Path: /upload
Method: POST
RestApiId: !Ref RestApi
Environment:
Variables:
BUCKET_NAME: !Ref S3Bucket
Policies:
- S3ReadPolicy:
BucketName: !Ref S3Bucket
- S3WritePolicy:
BucketName: !Ref S3Bucket
Metadata:
BuildMethod: esbuild
BuildProperties:
EntryPoints:
- index.js
// index.ts
import type { LambdaInterface } from '@aws-lambda-powertools/commons/types';
import { parser } from '@aws-lambda-powertools/parser';
import { ApiGatewayEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { Tracer } from '@aws-lambda-powertools/tracer';
import Logger from '@fec-module/logger';
import { z } from 'zod';
import { uploadFileSchema } from 'packages/backend/src/upload-file/schema';
const tracer = new Tracer();
type UploadInput = z.infer<typeof uploadFileSchema>;
type UploadResponse = {
cookies?: string[];
isBase64Encoded?: true | false;
statusCode: number;
headers?: { [header: string]: string | number | boolean };
body?: string;
};
class Lambda implements LambdaInterface {
@Logger.injectLambdaContext({ logEvent: true })
@tracer.captureLambdaHandler()
@parser({ schema: uploadFileSchema, envelope: ApiGatewayEnvelope })
public async handler(event: UploadInput): Promise<UploadResponse> {
Logger.info('Received context', event);
return {
statusCode: 200,
body: JSON.stringify({
message: 'Request Received successfully with body',
metadata: event.metadata,
}),
};
}
}
// schema.ts
const uploadFileSchema = z.object({
metadata: z.object({
source_system: z.string(),
category: z.string(),
filename: z.string(),
display_name: z.string().optional(),
external_id: z.string().optional(),
description: z.string().optional(),
ttl: z.number().optional(),
application_metadata: z.record(z.unknown()).optional(),
}),
});
Steps to Reproduce
- deploy the Api Gateway and the Lambda using SAM
- go to the Test tab of the
/upload
route in the Api Gateway AWS Console - place following headers :
{
"metadata": {
"source_system": "source_system",
"category": "category",
"filename": "filename",
"display_name": "display_name",
"external_id": "external_id",
"description": "descrition",
"ttl": 1,
"application_metadata": {
"other": "other"
}
}
}
- run test
following conversation in the Discord: https://discord.com/channels/1006478942305263677/1006527385409179678/1239877018653560872
(related to aws-powertools/powertools-lambda-python/issues/1562)
Possible Solution
update the Api Gateway zod schema to be:
z.union([z.string().ip(), z.literal('test-invoke-source-ip')]).optional()
Powertools for AWS Lambda (TypeScript) version
2.1.1-beta
AWS Lambda function runtime
20.x
Packaging format used
npm
Execution logs
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Shipped