diff --git a/packages/event-handler/src/rest/Router.ts b/packages/event-handler/src/rest/Router.ts index 9687afdcf5..cd6525d2c2 100644 --- a/packages/event-handler/src/rest/Router.ts +++ b/packages/event-handler/src/rest/Router.ts @@ -48,9 +48,13 @@ import { Route } from './Route.js'; import { RouteHandlerRegistry } from './RouteHandlerRegistry.js'; import { composeMiddleware, + getBase64EncodingFromHeaders, + getBase64EncodingFromResult, + getStatusCode, HttpResponseStream, isAPIGatewayProxyEventV1, isAPIGatewayProxyEventV2, + isBinaryResult, isExtendedAPIGatewayProxyResult, resolvePrefixedPath, } from './utils.js'; @@ -260,29 +264,30 @@ class Router { const route = this.routeRegistry.resolve(method, path); const handlerMiddleware: Middleware = async ({ reqCtx, next }) => { + let handlerRes: HandlerResponse; if (route === null) { - const notFoundRes = await this.handleError( + handlerRes = await this.handleError( new NotFoundError(`Route ${path} for method ${method} not found`), { ...reqCtx, scope: options?.scope } ); - reqCtx.res = handlerResultToWebResponse( - notFoundRes, - reqCtx.res.headers - ); } else { const handler = options?.scope == null ? route.handler : route.handler.bind(options.scope); - const handlerResult = await handler(reqCtx); + handlerRes = await handler(reqCtx); + } - reqCtx.res = handlerResultToWebResponse( - handlerResult, - reqCtx.res.headers - ); + if (getBase64EncodingFromResult(handlerRes)) { + reqCtx.isBase64Encoded = true; } + reqCtx.res = handlerResultToWebResponse(handlerRes, { + statusCode: getStatusCode(handlerRes), + resHeaders: reqCtx.res.headers, + }); + await next(); }; @@ -300,10 +305,10 @@ class Router { // middleware result takes precedence to allow short-circuiting if (middlewareResult !== undefined) { - requestContext.res = handlerResultToWebResponse( - middlewareResult, - requestContext.res.headers - ); + requestContext.res = handlerResultToWebResponse(middlewareResult, { + statusCode: getStatusCode(middlewareResult), + resHeaders: requestContext.res.headers, + }); } return requestContext; @@ -313,10 +318,16 @@ class Router { ...requestContext, scope: options?.scope, }); - requestContext.res = handlerResultToWebResponse( - res, - requestContext.res.headers - ); + + if (getBase64EncodingFromResult(res)) { + requestContext.isBase64Encoded = true; + } + + requestContext.res = handlerResultToWebResponse(res, { + statusCode: getStatusCode(res, HttpStatusCodes.INTERNAL_SERVER_ERROR), + resHeaders: requestContext.res.headers, + }); + return requestContext; } } @@ -353,7 +364,12 @@ class Router { options?: ResolveOptions ): Promise { const reqCtx = await this.#resolve(event, context, options); - return webResponseToProxyResult(reqCtx.res, reqCtx.responseType); + const isBase64Encoded = + reqCtx.isBase64Encoded ?? + getBase64EncodingFromHeaders(reqCtx.res.headers); + return webResponseToProxyResult(reqCtx.res, reqCtx.responseType, { + isBase64Encoded, + }); } /** @@ -434,7 +450,11 @@ class Router { try { const { scope, ...reqCtx } = options; const body = await handler.apply(scope ?? this, [error, reqCtx]); - if (body instanceof Response || isExtendedAPIGatewayProxyResult(body)) { + if ( + body instanceof Response || + isExtendedAPIGatewayProxyResult(body) || + isBinaryResult(body) + ) { return body; } if (!body.statusCode) { diff --git a/packages/event-handler/src/rest/converters.ts b/packages/event-handler/src/rest/converters.ts index bed552cff7..08b366c097 100644 --- a/packages/event-handler/src/rest/converters.ts +++ b/packages/event-handler/src/rest/converters.ts @@ -7,18 +7,20 @@ import type { APIGatewayProxyStructuredResultV2, } from 'aws-lambda'; import type { - CompressionOptions, ExtendedAPIGatewayProxyResult, ExtendedAPIGatewayProxyResultBody, HandlerResponse, + HttpStatusCode, ResponseType, ResponseTypeMap, V1Headers, + WebResponseToProxyResultOptions, } from '../types/rest.js'; -import { COMPRESSION_ENCODING_TYPES } from './constants.js'; +import { HttpStatusCodes } from './constants.js'; import { InvalidHttpMethodError } from './errors.js'; import { isAPIGatewayProxyEventV2, + isBinaryResult, isExtendedAPIGatewayProxyResult, isHttpMethod, isNodeReadableStream, @@ -213,41 +215,29 @@ const webHeadersToApiGatewayHeaders = ( : { headers: Record }; }; +const responseBodyToBase64 = async (response: Response) => { + const buffer = await response.arrayBuffer(); + return Buffer.from(buffer).toString('base64'); +}; + /** * Converts a Web API Response object to an API Gateway V1 proxy result. * * @param response - The Web API Response object + * @param isBase64Encoded - Whether the response body should be base64 encoded (e.g., for binary or compressed content) * @returns An API Gateway V1 proxy result */ const webResponseToProxyResultV1 = async ( - response: Response + response: Response, + isBase64Encoded?: boolean ): Promise => { const { headers, multiValueHeaders } = webHeadersToApiGatewayV1Headers( response.headers ); - // Check if response contains compressed/binary content - const contentEncoding = response.headers.get( - 'content-encoding' - ) as CompressionOptions['encoding']; - let body: string; - let isBase64Encoded = false; - - if ( - contentEncoding && - [ - COMPRESSION_ENCODING_TYPES.GZIP, - COMPRESSION_ENCODING_TYPES.DEFLATE, - ].includes(contentEncoding) - ) { - // For compressed content, get as buffer and encode to base64 - const buffer = await response.arrayBuffer(); - body = Buffer.from(buffer).toString('base64'); - isBase64Encoded = true; - } else { - // For text content, use text() - body = await response.text(); - } + const body = isBase64Encoded + ? await responseBodyToBase64(response) + : await response.text(); const result: APIGatewayProxyResult = { statusCode: response.status, @@ -267,10 +257,12 @@ const webResponseToProxyResultV1 = async ( * Converts a Web API Response object to an API Gateway V2 proxy result. * * @param response - The Web API Response object + * @param isBase64Encoded - Whether the response body should be base64 encoded (e.g., for binary or compressed content) * @returns An API Gateway V2 proxy result */ const webResponseToProxyResultV2 = async ( - response: Response + response: Response, + isBase64Encoded?: boolean ): Promise => { const headers: Record = {}; const cookies: string[] = []; @@ -283,25 +275,9 @@ const webResponseToProxyResultV2 = async ( } } - const contentEncoding = response.headers.get( - 'content-encoding' - ) as CompressionOptions['encoding']; - let body: string; - let isBase64Encoded = false; - - if ( - contentEncoding && - [ - COMPRESSION_ENCODING_TYPES.GZIP, - COMPRESSION_ENCODING_TYPES.DEFLATE, - ].includes(contentEncoding) - ) { - const buffer = await response.arrayBuffer(); - body = Buffer.from(buffer).toString('base64'); - isBase64Encoded = true; - } else { - body = await response.text(); - } + const body = isBase64Encoded + ? await responseBodyToBase64(response) + : await response.text(); const result: APIGatewayProxyStructuredResultV2 = { statusCode: response.status, @@ -319,12 +295,18 @@ const webResponseToProxyResultV2 = async ( const webResponseToProxyResult = ( response: Response, - responseType: T + responseType: T, + options?: WebResponseToProxyResultOptions ): Promise => { + const isBase64Encoded = options?.isBase64Encoded ?? false; if (responseType === 'ApiGatewayV1') { - return webResponseToProxyResultV1(response) as Promise; + return webResponseToProxyResultV1(response, isBase64Encoded) as Promise< + ResponseTypeMap[T] + >; } - return webResponseToProxyResultV2(response) as Promise; + return webResponseToProxyResultV2(response, isBase64Encoded) as Promise< + ResponseTypeMap[T] + >; }; /** @@ -365,13 +347,15 @@ function addProxyEventHeaders( * Handles APIGatewayProxyResult, Response objects, and plain objects. * * @param response - The handler response (APIGatewayProxyResult, Response, or plain object) - * @param resHeaders - Optional headers to be included in the response + * @param options - Optional configuration with statusCode and resHeaders * @returns A Web API Response object */ const handlerResultToWebResponse = ( response: HandlerResponse, - resHeaders?: Headers + options?: { statusCode?: HttpStatusCode; resHeaders?: Headers } ): Response => { + const statusCode = options?.statusCode ?? HttpStatusCodes.OK; + const resHeaders = options?.resHeaders; if (response instanceof Response) { if (resHeaders === undefined) return response; const headers = new Headers(resHeaders); @@ -385,6 +369,19 @@ const handlerResultToWebResponse = ( } const headers = new Headers(resHeaders); + + if (isBinaryResult(response)) { + const body = + response instanceof Readable + ? (Readable.toWeb(response) as ReadableStream) + : response; + + return new Response(body, { + status: statusCode, + headers, + }); + } + headers.set('Content-Type', 'application/json'); if (isExtendedAPIGatewayProxyResult(response)) { @@ -400,7 +397,7 @@ const handlerResultToWebResponse = ( headers, }); } - return Response.json(response, { headers }); + return Response.json(response, { headers, status: statusCode }); }; /** diff --git a/packages/event-handler/src/rest/utils.ts b/packages/event-handler/src/rest/utils.ts index 1b7c197171..409103d79d 100644 --- a/packages/event-handler/src/rest/utils.ts +++ b/packages/event-handler/src/rest/utils.ts @@ -7,15 +7,19 @@ import { import type { APIGatewayProxyEvent, APIGatewayProxyEventV2 } from 'aws-lambda'; import type { CompiledRoute, + CompressionOptions, ExtendedAPIGatewayProxyResult, HandlerResponse, HttpMethod, + HttpStatusCode, Middleware, Path, ResponseStream, ValidationResult, } from '../types/rest.js'; import { + COMPRESSION_ENCODING_TYPES, + HttpStatusCodes, HttpVerbs, PARAM_PATTERN, SAFE_CHARS, @@ -156,6 +160,16 @@ export const isWebReadableStream = ( ); }; +export const isBinaryResult = ( + value: unknown +): value is ArrayBuffer | Readable | ReadableStream => { + return ( + value instanceof ArrayBuffer || + isNodeReadableStream(value) || + isWebReadableStream(value) + ); +}; + /** * Type guard to check if the provided result is an API Gateway Proxy result. * @@ -318,3 +332,56 @@ export const HttpResponseStream = return underlyingStream; } }; + +export const getBase64EncodingFromResult = (result: HandlerResponse) => { + if (isBinaryResult(result)) { + return true; + } + if (isExtendedAPIGatewayProxyResult(result)) { + return isBinaryResult(result); + } + return false; +}; + +export const getBase64EncodingFromHeaders = (headers: Headers): boolean => { + const contentEncoding = headers.get( + 'content-encoding' + ) as CompressionOptions['encoding']; + + if ( + contentEncoding != null && + [ + COMPRESSION_ENCODING_TYPES.GZIP, + COMPRESSION_ENCODING_TYPES.DEFLATE, + ].includes(contentEncoding) + ) { + return true; + } + + const contentType = headers.get('content-type'); + if (contentType != null) { + const type = contentType.split(';')[0].trim(); + if ( + type.startsWith('image/') || + type.startsWith('audio/') || + type.startsWith('video/') + ) { + return true; + } + } + + return false; +}; + +export const getStatusCode = ( + result: HandlerResponse, + fallback: HttpStatusCode = HttpStatusCodes.OK +): HttpStatusCode => { + if (result instanceof Response) { + return result.status as HttpStatusCode; + } + if (isExtendedAPIGatewayProxyResult(result)) { + return result.statusCode as HttpStatusCode; + } + return fallback; +}; diff --git a/packages/event-handler/src/types/rest.ts b/packages/event-handler/src/types/rest.ts index ceb4c9a3ee..c5652d0e70 100644 --- a/packages/event-handler/src/types/rest.ts +++ b/packages/event-handler/src/types/rest.ts @@ -29,6 +29,7 @@ type RequestContext = { res: Response; params: Record; responseType: ResponseType; + isBase64Encoded?: boolean; }; type ErrorResolveOptions = RequestContext & ResolveOptions; @@ -69,14 +70,20 @@ interface CompiledRoute { type DynamicRoute = Route & CompiledRoute; -type ExtendedAPIGatewayProxyResultBody = string | Readable | ReadableStream; +type BinaryResult = ArrayBuffer | Readable | ReadableStream; + +type ExtendedAPIGatewayProxyResultBody = BinaryResult | string; type ExtendedAPIGatewayProxyResult = Omit & { body: ExtendedAPIGatewayProxyResultBody; cookies?: string[]; }; -type HandlerResponse = Response | JSONObject | ExtendedAPIGatewayProxyResult; +type HandlerResponse = + | Response + | JSONObject + | ExtendedAPIGatewayProxyResult + | BinaryResult; type RouteHandler = ( reqCtx: RequestContext @@ -230,7 +237,12 @@ type CompressionOptions = { threshold?: number; }; +type WebResponseToProxyResultOptions = { + isBase64Encoded?: boolean; +}; + export type { + BinaryResult, ExtendedAPIGatewayProxyResult, ExtendedAPIGatewayProxyResultBody, CompiledRoute, @@ -259,4 +271,5 @@ export type { CompressionOptions, NextFunction, V1Headers, + WebResponseToProxyResultOptions, }; diff --git a/packages/event-handler/tests/unit/rest/Router/basic-routing.test.ts b/packages/event-handler/tests/unit/rest/Router/basic-routing.test.ts index 555c33c6e8..01695dda7d 100644 --- a/packages/event-handler/tests/unit/rest/Router/basic-routing.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/basic-routing.test.ts @@ -1,3 +1,4 @@ +import { Readable } from 'node:stream'; import context from '@aws-lambda-powertools/testing-utils/context'; import { describe, expect, it, vi } from 'vitest'; import { InvalidEventError } from '../../../../src/rest/errors.js'; @@ -273,3 +274,109 @@ describe('Class: Router - V2 Cookies Support', () => { }); }); }); + +describe.each([ + { version: 'V1', createEvent: createTestEvent }, + { version: 'V2', createEvent: createTestEventV2 }, +])('Class: Router - Binary Result ($version)', ({ createEvent }) => { + it('handles ArrayBuffer as direct return type', async () => { + // Prepare + const app = new Router(); + const { buffer } = new TextEncoder().encode('binary data'); + app.get('/binary', () => buffer); + + // Act + const result = await app.resolve(createEvent('/binary', 'GET'), context); + + // Assess + expect(result.body).toBe(Buffer.from(buffer).toString('base64')); + expect(result.isBase64Encoded).toBe(true); + }); + + it('handles Readable stream as direct return type', async () => { + // Prepare + const app = new Router(); + const data = Buffer.concat([Buffer.from('chunk1'), Buffer.from('chunk2')]); + const stream = Readable.from([ + Buffer.from('chunk1'), + Buffer.from('chunk2'), + ]); + app.get('/stream', () => stream); + + // Act + const result = await app.resolve(createEvent('/stream', 'GET'), context); + + // Assess + expect(result.body).toBe(data.toString('base64')); + expect(result.isBase64Encoded).toBe(true); + }); + + it('handles ReadableStream as direct return type', async () => { + // Prepare + const app = new Router(); + const data = new TextEncoder().encode('data'); + const webStream = new ReadableStream({ + start(controller) { + controller.enqueue(data); + controller.close(); + }, + }); + app.get('/webstream', () => webStream); + + // Act + const result = await app.resolve(createEvent('/webstream', 'GET'), context); + + // Assess + expect(result.body).toBe(Buffer.from(data).toString('base64')); + expect(result.isBase64Encoded).toBe(true); + }); + + it.each([['image/png'], ['image/jpeg'], ['audio/mpeg'], ['video/mp4']])( + 'sets isBase64Encoded for %s content-type', + async (contentType) => { + // Prepare + const app = new Router(); + app.get( + '/media', + () => + new Response('binary data', { + headers: { 'content-type': contentType }, + }) + ); + + // Act + const result = await app.resolve(createEvent('/media', 'GET'), context); + + // Assess + expect(result).toEqual({ + statusCode: 200, + body: Buffer.from('binary data').toString('base64'), + headers: { 'content-type': contentType }, + isBase64Encoded: true, + }); + } + ); + + it('does not set isBase64Encoded for text content-types', async () => { + // Prepare + const app = new Router(); + app.get( + '/text', + () => + new Response('text data', { + headers: { 'content-type': 'text/plain' }, + }) + ); + + // Act + const result = await app.resolve(createEvent('/text', 'GET'), context); + + // Assess + expect(result).toEqual({ + statusCode: 200, + body: 'text data', + headers: { 'content-type': 'text/plain' }, + isBase64Encoded: false, + }); + }); +}); diff --git a/packages/event-handler/tests/unit/rest/Router/error-handling.test.ts b/packages/event-handler/tests/unit/rest/Router/error-handling.test.ts index 6e3ac82e66..00b83f7d02 100644 --- a/packages/event-handler/tests/unit/rest/Router/error-handling.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/error-handling.test.ts @@ -587,6 +587,46 @@ describe.each([ errorName: 'Error', }); }); + + it('handles BinaryResult from error handlers', async () => { + // Prepare + const app = new Router(); + const { buffer } = new TextEncoder().encode('error binary data'); + + class CustomError extends Error {} + + app.errorHandler(CustomError, async () => buffer); + app.get('/error', () => { + throw new CustomError('test error'); + }); + + // Act + const result = await app.resolve(createEvent('/error', 'GET'), context); + + // Assess + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); + expect(result.isBase64Encoded).toBe(true); + expect(result.body).toBe(Buffer.from(buffer).toString('base64')); + }); + + it('sets isBase64Encoded when notFound handler returns BinaryResult', async () => { + // Prepare + const app = new Router(); + const buffer = new TextEncoder().encode('not found binary'); + + app.notFound(async () => buffer.buffer); + + // Act + const result = await app.resolve( + createEvent('/nonexistent', 'GET'), + context + ); + + // Assess + expect(result.statusCode).toBe(HttpStatusCodes.OK); + expect(result.isBase64Encoded).toBe(true); + expect(result.body).toBe(Buffer.from(buffer.buffer).toString('base64')); + }); }); describe('Class: Router - proxyEventToWebRequest Error Handling', () => { beforeEach(() => { diff --git a/packages/event-handler/tests/unit/rest/converters.test.ts b/packages/event-handler/tests/unit/rest/converters.test.ts index 050a5731d4..f83d495c44 100644 --- a/packages/event-handler/tests/unit/rest/converters.test.ts +++ b/packages/event-handler/tests/unit/rest/converters.test.ts @@ -5,6 +5,7 @@ import { webHeadersToApiGatewayHeaders, } from '../../../src/rest/converters.js'; import { + HttpStatusCodes, handlerResultToWebResponse, proxyEventToWebRequest, webResponseToProxyResult, @@ -641,7 +642,7 @@ describe('Converters', () => { expect(result.body).toBe(''); }); - it('handles compressed response body', async () => { + it('respects isBase64Encoded option', async () => { // Prepare const response = new Response('Hello World', { status: 200, @@ -651,7 +652,9 @@ describe('Converters', () => { }); // Act - const result = await webResponseToProxyResult(response, 'ApiGatewayV1'); + const result = await webResponseToProxyResult(response, 'ApiGatewayV1', { + isBase64Encoded: true, + }); // Assess expect(result.isBase64Encoded).toBe(true); @@ -763,7 +766,7 @@ describe('Converters', () => { expect(result.body).toBe(''); }); - it('handles compressed response body', async () => { + it('respects isBase64Encoded option', async () => { // Prepare const response = new Response('Hello World', { status: 200, @@ -773,7 +776,9 @@ describe('Converters', () => { }); // Act - const result = await webResponseToProxyResult(response, 'ApiGatewayV2'); + const result = await webResponseToProxyResult(response, 'ApiGatewayV2', { + isBase64Encoded: true, + }); // Assess expect(result.isBase64Encoded).toBe(true); @@ -785,7 +790,7 @@ describe('Converters', () => { it('converts APIGatewayProxyResult to Response', async () => { // Prepare const proxyResult = { - statusCode: 201, + statusCode: HttpStatusCodes.CREATED, body: 'Hello World', headers: { 'content-type': 'text/plain' }, isBase64Encoded: false, @@ -796,7 +801,7 @@ describe('Converters', () => { // Assess expect(result).toBeInstanceOf(Response); - expect(result.status).toBe(201); + expect(result.status).toBe(HttpStatusCodes.CREATED); expect(await result.text()).toBe('Hello World'); expect(result.headers.get('content-type')).toBe('text/plain'); }); @@ -804,7 +809,7 @@ describe('Converters', () => { it('converts APIGatewayProxyResult with multiValueHeaders', () => { // Prepare const proxyResult = { - statusCode: 200, + statusCode: HttpStatusCodes.OK, body: 'test', headers: { 'content-type': 'application/json' }, multiValueHeaders: { @@ -817,6 +822,7 @@ describe('Converters', () => { const result = handlerResultToWebResponse(proxyResult); // Assess + expect(result.status).toBe(HttpStatusCodes.OK); expect(result.headers.get('content-type')).toBe('application/json'); expect(result.headers.get('Set-Cookie')).toBe( 'cookie1=value1, cookie2=value2' @@ -832,7 +838,7 @@ describe('Converters', () => { // Assess expect(result).toBeInstanceOf(Response); - expect(result.status).toBe(200); + expect(result.status).toBe(HttpStatusCodes.OK); expect(result.text()).resolves.toBe(JSON.stringify(obj)); expect(result.headers.get('Content-Type')).toBe('application/json'); }); @@ -843,7 +849,10 @@ describe('Converters', () => { const headers = new Headers({ 'x-custom': 'value' }); // Act - const result = handlerResultToWebResponse(obj, headers); + const result = handlerResultToWebResponse(obj, { + statusCode: HttpStatusCodes.OK, + resHeaders: headers, + }); // Assess expect(result.headers.get('Content-Type')).toBe('application/json'); @@ -853,7 +862,7 @@ describe('Converters', () => { it('handles APIGatewayProxyResult with undefined headers', () => { // Prepare const proxyResult = { - statusCode: 200, + statusCode: HttpStatusCodes.OK, body: 'test', headers: undefined, isBase64Encoded: false, @@ -864,13 +873,13 @@ describe('Converters', () => { // Assess expect(result).toBeInstanceOf(Response); - expect(result.status).toBe(200); + expect(result.status).toBe(HttpStatusCodes.OK); }); it('handles APIGatewayProxyResult with undefined multiValueHeaders', () => { // Prepare const proxyResult = { - statusCode: 200, + statusCode: HttpStatusCodes.OK, body: 'test', headers: { 'content-type': 'text/plain' }, multiValueHeaders: undefined, @@ -881,13 +890,14 @@ describe('Converters', () => { const result = handlerResultToWebResponse(proxyResult); // Assess + expect(result.status).toBe(HttpStatusCodes.OK); expect(result.headers.get('content-type')).toBe('text/plain'); }); it('handles APIGatewayProxyResult with undefined values in multiValueHeaders', () => { // Prepare const proxyResult = { - statusCode: 200, + statusCode: HttpStatusCodes.OK, body: 'test', headers: { 'content-type': 'text/plain' }, multiValueHeaders: { 'Set-Cookie': undefined }, @@ -898,6 +908,7 @@ describe('Converters', () => { const result = handlerResultToWebResponse(proxyResult); // Assess + expect(result.status).toBe(HttpStatusCodes.OK); expect(result.headers.get('content-type')).toBe('text/plain'); }); @@ -912,19 +923,22 @@ describe('Converters', () => { }); // Act - const result = handlerResultToWebResponse(response, resHeaders); + const result = handlerResultToWebResponse(response, { + statusCode: HttpStatusCodes.OK, + resHeaders, + }); // Assess + expect(result.status).toBe(HttpStatusCodes.OK); expect(result.headers.get('content-type')).toBe('text/plain'); expect(result.headers.get('x-custom')).toBe('value'); - expect(result.status).toBe(200); expect(result.text()).resolves.toBe('Hello'); }); it('returns Response object as-is when resHeaders is undefined', () => { // Prepare const response = new Response('Hello', { - status: 201, + status: HttpStatusCodes.CREATED, headers: { 'content-type': 'text/plain' }, }); @@ -933,6 +947,7 @@ describe('Converters', () => { // Assess expect(result).toBe(response); + expect(result.status).toBe(HttpStatusCodes.CREATED); }); }); diff --git a/packages/event-handler/tests/unit/rest/utils.test.ts b/packages/event-handler/tests/unit/rest/utils.test.ts index 56176c2782..0beff14dce 100644 --- a/packages/event-handler/tests/unit/rest/utils.test.ts +++ b/packages/event-handler/tests/unit/rest/utils.test.ts @@ -621,6 +621,7 @@ describe('Path Utilities', () => { params: {}, event: {} as APIGatewayProxyEvent, context: {} as Context, + responseType: 'ApiGatewayV1', req: new Request('https://example.com'), res: new Response(), };