From b77f08d6bbf7a8a5c016786f3e9ac43bf533e2d8 Mon Sep 17 00:00:00 2001 From: conico974 Date: Mon, 7 Apr 2025 22:35:11 +0200 Subject: [PATCH 1/5] add aws-lambda-compressed --- .../open-next/src/build/validateConfig.ts | 1 + .../wrappers/aws-lambda-compressed.ts | 136 ++++++++++++++++++ packages/open-next/src/types/open-next.ts | 1 + 3 files changed, 138 insertions(+) create mode 100644 packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts diff --git a/packages/open-next/src/build/validateConfig.ts b/packages/open-next/src/build/validateConfig.ts index acb3b3ae1..ecb3cda19 100644 --- a/packages/open-next/src/build/validateConfig.ts +++ b/packages/open-next/src/build/validateConfig.ts @@ -15,6 +15,7 @@ const compatibilityMatrix: Record = { "aws-cloudfront", "sqs-revalidate", ], + "aws-lambda-compressed": ["aws-apigw-v2"], "aws-lambda-streaming": ["aws-apigw-v2"], cloudflare: ["edge"], "cloudflare-edge": ["edge"], diff --git a/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts b/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts new file mode 100644 index 000000000..f979e14a1 --- /dev/null +++ b/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts @@ -0,0 +1,136 @@ +import { Readable, Writable } from "node:stream"; +import type { ReadableStream } from "node:stream/web"; +import zlib from "node:zlib"; + +import type { + APIGatewayProxyEvent, + APIGatewayProxyEventV2, + APIGatewayProxyResult, + APIGatewayProxyResultV2, + CloudFrontRequestEvent, + CloudFrontRequestResult, +} from "aws-lambda"; +import type { WrapperHandler } from "types/overrides"; + +import type { InternalResult, StreamCreator } from "types/open-next"; +import { error } from "../../adapters/logger"; +import type { + WarmerEvent, + WarmerResponse, +} from "../../adapters/warmer-function"; + +type AwsLambdaEvent = + | APIGatewayProxyEventV2 + | CloudFrontRequestEvent + | APIGatewayProxyEvent + | WarmerEvent; + +type AwsLambdaReturn = + | APIGatewayProxyResultV2 + | APIGatewayProxyResult + | CloudFrontRequestResult + | WarmerResponse; + +function formatWarmerResponse(event: WarmerEvent) { + return new Promise((resolve) => { + setTimeout(() => { + resolve({ serverId, type: "warmer" } satisfies WarmerResponse); + }, event.delay); + }); +} + +const handler: WrapperHandler = + async (handler, converter) => + async (event: AwsLambdaEvent): Promise => { + // Handle warmer event + if ("type" in event) { + return formatWarmerResponse(event); + } + + const internalEvent = await converter.convertFrom(event); + //TODO: create a simple reproduction and open an issue in the node repo + //This is a workaround, there is an issue in node that causes node to crash silently if the OpenNextNodeResponse stream is not consumed + //This does not happen everytime, it's probably caused by suspended component in ssr (either via or loading.tsx) + //Everyone that wish to create their own wrapper without a StreamCreator should implement this workaround + //This is not necessary if the underlying handler does not use OpenNextNodeResponse (At the moment, OpenNextNodeResponse is used by the node runtime servers and the image server) + const fakeStream: StreamCreator = { + writeHeaders: () => { + return new Writable({ + write: (_chunk, _encoding, callback) => { + callback(); + }, + }); + }, + }; + + const acceptEncoding = + internalEvent.headers["accept-encoding"] ?? + internalEvent.headers["Accept-Encoding"] ?? + ""; + + let contentEncoding: string | null = null; + if (acceptEncoding?.includes("br")) { + contentEncoding = "br"; + } else if (acceptEncoding?.includes("gzip")) { + contentEncoding = "gzip"; + } else if (acceptEncoding?.includes("deflate")) { + contentEncoding = "deflate"; + } + + const handlerResponse = await handler(internalEvent, { + streamCreator: fakeStream, + }); + + const response: InternalResult = { + ...handlerResponse, + body: compressBody(handlerResponse.body, contentEncoding), + headers: { + ...handlerResponse.headers, + ...(contentEncoding ? { "content-encoding": contentEncoding } : {}), + }, + isBase64Encoded: !!contentEncoding || handlerResponse.isBase64Encoded, + }; + + return converter.convertTo(response, event); + }; + +export default { + wrapper: handler, + name: "aws-lambda-compressed", + supportStreaming: false, +}; + +function compressBody(body: ReadableStream, encoding: string | null) { + // If no encoding is specified, return original body + if (!encoding) return body; + try { + const readable = Readable.fromWeb(body); + + switch (encoding) { + case "br": + return Readable.toWeb( + readable.pipe( + zlib.createBrotliCompress({ + params: { + // This is a compromise between speed and compression ratio. + // The default one will most likely timeout an AWS Lambda with default configuration on large bodies (>6mb). + // Therefore we set it to 6, which is a good compromise. + [zlib.constants.BROTLI_PARAM_QUALITY]: + Number(process.env.BROTLI_QUALITY) ?? 6, + }, + }), + ), + ); + case "gzip": + return Readable.toWeb(readable.pipe(zlib.createGzip())); + case "deflate": + return Readable.toWeb(readable.pipe(zlib.createDeflate())); + default: + return body; + } + } catch (e) { + error("Error compressing body:", e); + // Fall back to no compression on error + return body; + } +} diff --git a/packages/open-next/src/types/open-next.ts b/packages/open-next/src/types/open-next.ts index e307912d9..17ab7ca09 100644 --- a/packages/open-next/src/types/open-next.ts +++ b/packages/open-next/src/types/open-next.ts @@ -94,6 +94,7 @@ export interface Origin { export type IncludedWrapper = | "aws-lambda" | "aws-lambda-streaming" + | "aws-lambda-compressed" | "node" // @deprecated - use "cloudflare-edge" instead. | "cloudflare" From 9d194c4884d0d747ee0b23ab993c38811e8a07b9 Mon Sep 17 00:00:00 2001 From: magnus Date: Tue, 8 Apr 2025 21:23:30 +0200 Subject: [PATCH 2/5] changeset --- .changeset/bright-bulldogs-laugh.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/bright-bulldogs-laugh.md diff --git a/.changeset/bright-bulldogs-laugh.md b/.changeset/bright-bulldogs-laugh.md new file mode 100644 index 000000000..a966311e8 --- /dev/null +++ b/.changeset/bright-bulldogs-laugh.md @@ -0,0 +1,9 @@ +--- +"@opennextjs/aws": patch +--- + +Add aws-lambda-compressed wrapper + +Introduces a new wrapper called `aws-lambda-compressed`. Will compress the response body by default. Compression will be applied in the following priority order: br (Brotli) → gzip → deflate. If none of these is found, we just return the body as is. + +The compression quality for brotli can be configured using the `BROTLI_QUALITY` environment variable. If not set, it defaults to 6. From c5da7b5a1ed304bc48b192174fa584f8fc49697d Mon Sep 17 00:00:00 2001 From: magnus Date: Wed, 9 Apr 2025 07:42:53 +0200 Subject: [PATCH 3/5] review --- .changeset/bright-bulldogs-laugh.md | 4 +- .../wrappers/aws-lambda-compressed.ts | 95 +++++++------------ .../src/overrides/wrappers/aws-lambda.ts | 38 +------- packages/open-next/src/types/overrides.ts | 21 ++++ packages/open-next/src/utils/overrides.ts | 9 ++ 5 files changed, 72 insertions(+), 95 deletions(-) create mode 100644 packages/open-next/src/utils/overrides.ts diff --git a/.changeset/bright-bulldogs-laugh.md b/.changeset/bright-bulldogs-laugh.md index a966311e8..a01a89563 100644 --- a/.changeset/bright-bulldogs-laugh.md +++ b/.changeset/bright-bulldogs-laugh.md @@ -4,6 +4,4 @@ Add aws-lambda-compressed wrapper -Introduces a new wrapper called `aws-lambda-compressed`. Will compress the response body by default. Compression will be applied in the following priority order: br (Brotli) → gzip → deflate. If none of these is found, we just return the body as is. - -The compression quality for brotli can be configured using the `BROTLI_QUALITY` environment variable. If not set, it defaults to 6. +New wrapper called `aws-lambda-compressed`. The compression quality for brotli can be configured using the `BROTLI_QUALITY` environment variable. If not set, it defaults to 6. \ No newline at end of file diff --git a/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts b/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts index f979e14a1..53cbdbd9c 100644 --- a/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts +++ b/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts @@ -1,43 +1,15 @@ -import { Readable, Writable } from "node:stream"; +import { Readable, type Transform, Writable } from "node:stream"; import type { ReadableStream } from "node:stream/web"; import zlib from "node:zlib"; -import type { - APIGatewayProxyEvent, - APIGatewayProxyEventV2, - APIGatewayProxyResult, - APIGatewayProxyResultV2, - CloudFrontRequestEvent, - CloudFrontRequestResult, -} from "aws-lambda"; -import type { WrapperHandler } from "types/overrides"; - import type { InternalResult, StreamCreator } from "types/open-next"; -import { error } from "../../adapters/logger"; import type { - WarmerEvent, - WarmerResponse, -} from "../../adapters/warmer-function"; - -type AwsLambdaEvent = - | APIGatewayProxyEventV2 - | CloudFrontRequestEvent - | APIGatewayProxyEvent - | WarmerEvent; - -type AwsLambdaReturn = - | APIGatewayProxyResultV2 - | APIGatewayProxyResult - | CloudFrontRequestResult - | WarmerResponse; - -function formatWarmerResponse(event: WarmerEvent) { - return new Promise((resolve) => { - setTimeout(() => { - resolve({ serverId, type: "warmer" } satisfies WarmerResponse); - }, event.delay); - }); -} + AwsLambdaEvent, + AwsLambdaReturn, + WrapperHandler, +} from "types/overrides"; +import { formatWarmerResponse } from "utils/overrides"; +import { error } from "../../adapters/logger"; const handler: WrapperHandler = async (handler, converter) => @@ -48,11 +20,7 @@ const handler: WrapperHandler = } const internalEvent = await converter.convertFrom(event); - //TODO: create a simple reproduction and open an issue in the node repo - //This is a workaround, there is an issue in node that causes node to crash silently if the OpenNextNodeResponse stream is not consumed - //This does not happen everytime, it's probably caused by suspended component in ssr (either via or loading.tsx) - //Everyone that wish to create their own wrapper without a StreamCreator should implement this workaround - //This is not necessary if the underlying handler does not use OpenNextNodeResponse (At the moment, OpenNextNodeResponse is used by the node runtime servers and the image server) + // This is a workaround, you can read more about it in the aws-lambda wrapper const fakeStream: StreamCreator = { writeHeaders: () => { return new Writable({ @@ -63,6 +31,18 @@ const handler: WrapperHandler = }, }; + const handlerResponse = await handler(internalEvent, { + streamCreator: fakeStream, + }); + + // Check if response is already compressed + const prevEncoding = + handlerResponse.headers?.["content-encoding"] ?? + handlerResponse.headers?.["Content-Encoding"] ?? + ""; + + // Return early here if the response is already compressed + const acceptEncoding = internalEvent.headers["accept-encoding"] ?? internalEvent.headers["Accept-Encoding"] ?? @@ -77,10 +57,6 @@ const handler: WrapperHandler = contentEncoding = "deflate"; } - const handlerResponse = await handler(internalEvent, { - streamCreator: fakeStream, - }); - const response: InternalResult = { ...handlerResponse, body: compressBody(handlerResponse.body, contentEncoding), @@ -105,29 +81,30 @@ function compressBody(body: ReadableStream, encoding: string | null) { if (!encoding) return body; try { const readable = Readable.fromWeb(body); + let transform: Transform; switch (encoding) { case "br": - return Readable.toWeb( - readable.pipe( - zlib.createBrotliCompress({ - params: { - // This is a compromise between speed and compression ratio. - // The default one will most likely timeout an AWS Lambda with default configuration on large bodies (>6mb). - // Therefore we set it to 6, which is a good compromise. - [zlib.constants.BROTLI_PARAM_QUALITY]: - Number(process.env.BROTLI_QUALITY) ?? 6, - }, - }), - ), - ); + transform = zlib.createBrotliCompress({ + params: { + // This is a compromise between speed and compression ratio. + // The default one will most likely timeout an AWS Lambda with default configuration on large bodies (>6mb). + // Therefore we set it to 6, which is a good compromise. + [zlib.constants.BROTLI_PARAM_QUALITY]: + Number(process.env.BROTLI_QUALITY) ?? 6, + }, + }); + break; case "gzip": - return Readable.toWeb(readable.pipe(zlib.createGzip())); + transform = zlib.createGzip(); + break; case "deflate": - return Readable.toWeb(readable.pipe(zlib.createDeflate())); + transform = zlib.createDeflate(); + break; default: return body; } + return Readable.toWeb(readable.pipe(transform)); } catch (e) { error("Error compressing body:", e); // Fall back to no compression on error diff --git a/packages/open-next/src/overrides/wrappers/aws-lambda.ts b/packages/open-next/src/overrides/wrappers/aws-lambda.ts index 6c45ee07c..3e2af16ad 100644 --- a/packages/open-next/src/overrides/wrappers/aws-lambda.ts +++ b/packages/open-next/src/overrides/wrappers/aws-lambda.ts @@ -1,40 +1,12 @@ import { Writable } from "node:stream"; -import type { - APIGatewayProxyEvent, - APIGatewayProxyEventV2, - APIGatewayProxyResult, - APIGatewayProxyResultV2, - CloudFrontRequestEvent, - CloudFrontRequestResult, -} from "aws-lambda"; -import type { WrapperHandler } from "types/overrides"; - import type { StreamCreator } from "types/open-next"; import type { - WarmerEvent, - WarmerResponse, -} from "../../adapters/warmer-function"; - -type AwsLambdaEvent = - | APIGatewayProxyEventV2 - | CloudFrontRequestEvent - | APIGatewayProxyEvent - | WarmerEvent; - -type AwsLambdaReturn = - | APIGatewayProxyResultV2 - | APIGatewayProxyResult - | CloudFrontRequestResult - | WarmerResponse; - -function formatWarmerResponse(event: WarmerEvent) { - return new Promise((resolve) => { - setTimeout(() => { - resolve({ serverId, type: "warmer" } satisfies WarmerResponse); - }, event.delay); - }); -} + AwsLambdaEvent, + AwsLambdaReturn, + WrapperHandler, +} from "types/overrides"; +import { formatWarmerResponse } from "utils/overrides"; const handler: WrapperHandler = async (handler, converter) => diff --git a/packages/open-next/src/types/overrides.ts b/packages/open-next/src/types/overrides.ts index 4ea257270..cea8ba710 100644 --- a/packages/open-next/src/types/overrides.ts +++ b/packages/open-next/src/types/overrides.ts @@ -2,6 +2,15 @@ import type { Readable } from "node:stream"; import type { Meta } from "types/cache"; +import type { + APIGatewayProxyEvent, + APIGatewayProxyEventV2, + APIGatewayProxyResult, + APIGatewayProxyResultV2, + CloudFrontRequestEvent, + CloudFrontRequestResult, +} from "aws-lambda"; +import type { WarmerEvent, WarmerResponse } from "../adapters/warmer-function"; import type { BaseEventOrResult, BaseOverride, @@ -229,3 +238,15 @@ type CDNPath = { export type CDNInvalidationHandler = BaseOverride & { invalidatePaths: (paths: CDNPath[]) => Promise; }; + +export type AwsLambdaEvent = + | APIGatewayProxyEventV2 + | CloudFrontRequestEvent + | APIGatewayProxyEvent + | WarmerEvent; + +export type AwsLambdaReturn = + | APIGatewayProxyResultV2 + | APIGatewayProxyResult + | CloudFrontRequestResult + | WarmerResponse; diff --git a/packages/open-next/src/utils/overrides.ts b/packages/open-next/src/utils/overrides.ts new file mode 100644 index 000000000..1ffafeadb --- /dev/null +++ b/packages/open-next/src/utils/overrides.ts @@ -0,0 +1,9 @@ +import type { WarmerEvent, WarmerResponse } from "../adapters/warmer-function"; + +export function formatWarmerResponse(event: WarmerEvent) { + return new Promise((resolve) => { + setTimeout(() => { + resolve({ serverId, type: "warmer" } satisfies WarmerResponse); + }, event.delay); + }); +} From 1d81a512718365bcfd48d9cd8ddfe2799ee70b65 Mon Sep 17 00:00:00 2001 From: magnus Date: Wed, 9 Apr 2025 10:50:17 +0200 Subject: [PATCH 4/5] review --- .../wrappers/aws-lambda-compressed.ts | 22 +++++++++-------- .../src/overrides/wrappers/aws-lambda.ts | 18 ++++++++++---- packages/open-next/src/types/aws-lambda.ts | 24 ++++++++++++++++++- packages/open-next/src/types/overrides.ts | 22 ----------------- packages/open-next/src/utils/overrides.ts | 9 ------- 5 files changed, 48 insertions(+), 47 deletions(-) delete mode 100644 packages/open-next/src/utils/overrides.ts diff --git a/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts b/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts index 53cbdbd9c..961ce6333 100644 --- a/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts +++ b/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts @@ -2,14 +2,11 @@ import { Readable, type Transform, Writable } from "node:stream"; import type { ReadableStream } from "node:stream/web"; import zlib from "node:zlib"; +import type { AwsLambdaEvent, AwsLambdaReturn } from "types/aws-lambda"; import type { InternalResult, StreamCreator } from "types/open-next"; -import type { - AwsLambdaEvent, - AwsLambdaReturn, - WrapperHandler, -} from "types/overrides"; -import { formatWarmerResponse } from "utils/overrides"; +import type { WrapperHandler } from "types/overrides"; import { error } from "../../adapters/logger"; +import { formatWarmerResponse } from "./aws-lambda"; const handler: WrapperHandler = async (handler, converter) => @@ -20,7 +17,8 @@ const handler: WrapperHandler = } const internalEvent = await converter.convertFrom(event); - // This is a workaround, you can read more about it in the aws-lambda wrapper + // This is a workaround + // https://github.com/opennextjs/opennextjs-aws/blob/e9b37fd44eb856eb8ae73168bf455ff85dd8b285/packages/open-next/src/overrides/wrappers/aws-lambda.ts#L49-L53 const fakeStream: StreamCreator = { writeHeaders: () => { return new Writable({ @@ -36,13 +34,17 @@ const handler: WrapperHandler = }); // Check if response is already compressed - const prevEncoding = - handlerResponse.headers?.["content-encoding"] ?? - handlerResponse.headers?.["Content-Encoding"] ?? + const alreadyEncoded = + handlerResponse.headers["content-encoding"] ?? + handlerResponse.headers["Content-Encoding"] ?? ""; // Return early here if the response is already compressed + if (alreadyEncoded) { + return converter.convertTo(handlerResponse, event); + } + // We compress the body if the client accepts it const acceptEncoding = internalEvent.headers["accept-encoding"] ?? internalEvent.headers["Accept-Encoding"] ?? diff --git a/packages/open-next/src/overrides/wrappers/aws-lambda.ts b/packages/open-next/src/overrides/wrappers/aws-lambda.ts index 3e2af16ad..fed3fb10c 100644 --- a/packages/open-next/src/overrides/wrappers/aws-lambda.ts +++ b/packages/open-next/src/overrides/wrappers/aws-lambda.ts @@ -1,12 +1,20 @@ import { Writable } from "node:stream"; +import type { AwsLambdaEvent, AwsLambdaReturn } from "types/aws-lambda"; import type { StreamCreator } from "types/open-next"; +import type { WrapperHandler } from "types/overrides"; import type { - AwsLambdaEvent, - AwsLambdaReturn, - WrapperHandler, -} from "types/overrides"; -import { formatWarmerResponse } from "utils/overrides"; + WarmerEvent, + WarmerResponse, +} from "../../adapters/warmer-function"; + +export function formatWarmerResponse(event: WarmerEvent) { + return new Promise((resolve) => { + setTimeout(() => { + resolve({ serverId, type: "warmer" } satisfies WarmerResponse); + }, event.delay); + }); +} const handler: WrapperHandler = async (handler, converter) => diff --git a/packages/open-next/src/types/aws-lambda.ts b/packages/open-next/src/types/aws-lambda.ts index f99a5412e..d2e4de2f2 100644 --- a/packages/open-next/src/types/aws-lambda.ts +++ b/packages/open-next/src/types/aws-lambda.ts @@ -1,5 +1,15 @@ import type { Writable } from "node:stream"; -import type { APIGatewayProxyEventV2, Context } from "aws-lambda"; + +import type { + APIGatewayProxyEvent, + APIGatewayProxyEventV2, + APIGatewayProxyResult, + APIGatewayProxyResultV2, + CloudFrontRequestEvent, + CloudFrontRequestResult, + Context, +} from "aws-lambda"; +import type { WarmerEvent, WarmerResponse } from "../adapters/warmer-function"; export interface ResponseStream extends Writable { getBufferedData(): Buffer; @@ -25,3 +35,15 @@ declare global { } } } + +export type AwsLambdaEvent = + | APIGatewayProxyEventV2 + | CloudFrontRequestEvent + | APIGatewayProxyEvent + | WarmerEvent; + +export type AwsLambdaReturn = + | APIGatewayProxyResultV2 + | APIGatewayProxyResult + | CloudFrontRequestResult + | WarmerResponse; diff --git a/packages/open-next/src/types/overrides.ts b/packages/open-next/src/types/overrides.ts index cea8ba710..81325c8b8 100644 --- a/packages/open-next/src/types/overrides.ts +++ b/packages/open-next/src/types/overrides.ts @@ -1,16 +1,6 @@ import type { Readable } from "node:stream"; import type { Meta } from "types/cache"; - -import type { - APIGatewayProxyEvent, - APIGatewayProxyEventV2, - APIGatewayProxyResult, - APIGatewayProxyResultV2, - CloudFrontRequestEvent, - CloudFrontRequestResult, -} from "aws-lambda"; -import type { WarmerEvent, WarmerResponse } from "../adapters/warmer-function"; import type { BaseEventOrResult, BaseOverride, @@ -238,15 +228,3 @@ type CDNPath = { export type CDNInvalidationHandler = BaseOverride & { invalidatePaths: (paths: CDNPath[]) => Promise; }; - -export type AwsLambdaEvent = - | APIGatewayProxyEventV2 - | CloudFrontRequestEvent - | APIGatewayProxyEvent - | WarmerEvent; - -export type AwsLambdaReturn = - | APIGatewayProxyResultV2 - | APIGatewayProxyResult - | CloudFrontRequestResult - | WarmerResponse; diff --git a/packages/open-next/src/utils/overrides.ts b/packages/open-next/src/utils/overrides.ts deleted file mode 100644 index 1ffafeadb..000000000 --- a/packages/open-next/src/utils/overrides.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { WarmerEvent, WarmerResponse } from "../adapters/warmer-function"; - -export function formatWarmerResponse(event: WarmerEvent) { - return new Promise((resolve) => { - setTimeout(() => { - resolve({ serverId, type: "warmer" } satisfies WarmerResponse); - }, event.delay); - }); -} From e1a54ccd227f3166ad957a0e7ef0132e73716bd5 Mon Sep 17 00:00:00 2001 From: magnus Date: Wed, 9 Apr 2025 16:31:33 +0200 Subject: [PATCH 5/5] lowercase --- .../src/overrides/wrappers/aws-lambda-compressed.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts b/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts index 961ce6333..80958668b 100644 --- a/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts +++ b/packages/open-next/src/overrides/wrappers/aws-lambda-compressed.ts @@ -34,10 +34,8 @@ const handler: WrapperHandler = }); // Check if response is already compressed - const alreadyEncoded = - handlerResponse.headers["content-encoding"] ?? - handlerResponse.headers["Content-Encoding"] ?? - ""; + // The handlers response headers are lowercase + const alreadyEncoded = handlerResponse.headers["content-encoding"] ?? ""; // Return early here if the response is already compressed if (alreadyEncoded) {