Skip to content

Feature request: Parse records as JSON and S3Schema in S3SqsEventNotificationRecordSchema #3525

Closed
@dreamorosi

Description

@dreamorosi

Discussed in #3449

Originally posted by cyrildewit December 30, 2024
Hi, I am implementing a Lambda handler that will consume a SQS queue filled with S3 event notifications. I expected that S3SqsEventNotificationSchema would also validate and parse the payload of the S3 Event Notification within the SQS Message, but that is currently not the case.

Here's a copy of the official schemas for easy reference source:

const S3SqsEventNotificationSchema = z.object({
  Records: z.array(S3SqsEventNotificationRecordSchema),
});

const S3SqsEventNotificationRecordSchema = SqsRecordSchema.extend({
  body: z.string(),
});

I wonder if this design decision was made on purpose?

I have solved it by creating a custom version of S3SqsEventNotificationSchema, like so:

const extendedS3SqsEventNotificationSchema = S3SqsEventNotificationSchema.extend({
    Records: z.array(SqsRecordSchema.extend({
        body: JSONStringified(S3Schema),
    })),
});
type ExtendedS3SqsEventNotification = z.infer<typeof extendedS3SqsEventNotificationSchema>;
Full code example for reference:
import type { SQSHandler } from 'aws-lambda';
import middy from '@middy/core';
import { Logger } from '@aws-lambda-powertools/logger';
import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware';
import { parser } from '@aws-lambda-powertools/parser/middleware';
import {
  S3Schema,
  S3SqsEventNotificationSchema,
  SqsRecordSchema,
} from '@aws-lambda-powertools/parser/schemas';
import { JSONStringified } from '@aws-lambda-powertools/parser/helpers';
import { BatchProcessor, EventType, processPartialResponse } from '@aws-lambda-powertools/batch';
import { z } from 'zod';

const processor = new BatchProcessor(EventType.SQS);

const logger = new Logger({
  logLevel: 'debug',
});

const extendedS3SqsEventNotificationSchema = S3SqsEventNotificationSchema.extend({
  Records: z.array(SqsRecordSchema.extend({
      body: JSONStringified(S3Schema),
  })),
});

type ExtendedS3SqsEventNotification = z.infer<typeof extendedS3SqsEventNotificationSchema>;

const recordHandler = async (record: ExtendedS3SqsEventNotification['Records'][number]): Promise<void> => {
  logger.debug('S3 Event Records', {
      s3EventRecords: record.body.Records,
  });
};

const lambdaSqsHandler: SQSHandler = async (event, context) =>
  processPartialResponse(event, recordHandler, processor, {
      context,
  });

export const handler = middy(lambdaSqsHandler)
  .use(injectLambdaContext(logger, { logEvent: true }))
  .use(parser({ schema: extendedS3SqsEventNotificationSchema }));

Metadata

Metadata

Assignees

Labels

completedThis item is complete and has been merged/shippedfeature-requestThis item refers to a feature request for an existing or new utilitygood-first-issueSomething that is suitable for those who want to start contributingparserThis item relates to the Parser Utility

Type

No type

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions