Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dirty-rabbits-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@opennextjs/aws": patch
---

perf(converters): Improve performance
3 changes: 2 additions & 1 deletion packages/open-next/src/core/routing/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import crypto from "node:crypto";

Check failure on line 1 in packages/open-next/src/core/routing/util.ts

View workflow job for this annotation

GitHub Actions / validate

format

File content differs from formatting output
import type { OutgoingHttpHeaders } from "node:http";
import { parse as parseQs, stringify as stringifyQs } from "node:querystring";

Expand Down Expand Up @@ -150,8 +150,9 @@
* @__PURE__
*/
export function convertToQuery(querystring: string) {
if (!querystring) return {};
const query = new URLSearchParams(querystring);
const queryObject: Record<string, string[] | string> = {};
const queryObject: Record<string, string[] | string> = {};

for (const key of query.keys()) {
const queries = query.getAll(key);
Expand Down
6 changes: 4 additions & 2 deletions packages/open-next/src/overrides/converters/aws-apigw-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ function normalizeAPIGatewayProxyEventV2Headers(
headers.cookie = cookies.join("; ");
}

for (const [key, value] of Object.entries(rawHeaders || {})) {
headers[key.toLowerCase()] = value!;
if (rawHeaders) {
for (const [key, value] of Object.entries(rawHeaders)) {
headers[key.toLowerCase()] = value!;
}
}

return headers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ function normalizeCloudFrontRequestEventHeaders(
const headers: Record<string, string> = {};

for (const [key, values] of Object.entries(rawHeaders)) {
const lowerKey = key.toLowerCase();
for (const { value } of values) {
if (value) {
headers[key.toLowerCase()] = value;
headers[lowerKey] = value;
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions packages/open-next/src/overrides/converters/edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ const converter: Converter<InternalEvent, InternalResult | MiddlewareResult> = {

const searchParams = url.searchParams;
const query = getQueryFromSearchParams(searchParams);
// Transform body into Buffer
const body = await event.arrayBuffer();
const headers: Record<string, string> = {};
event.headers.forEach((value, key) => {
headers[key] = value;
Expand All @@ -34,6 +32,11 @@ const converter: Converter<InternalEvent, InternalResult | MiddlewareResult> = {
const method = event.method;
const shouldHaveBody = method !== "GET" && method !== "HEAD";

// Only read body for methods that should have one
const body = shouldHaveBody
? Buffer.from(await event.arrayBuffer())
: undefined;

const cookieHeader = event.headers.get("cookie");
const cookies = cookieHeader
? (cookieParser.parse(cookieHeader) as Record<string, string>)
Expand All @@ -44,7 +47,7 @@ const converter: Converter<InternalEvent, InternalResult | MiddlewareResult> = {
method,
rawPath,
url: event.url,
body: shouldHaveBody ? Buffer.from(body) : undefined,
body,
headers,
remoteAddress: event.headers.get("x-forwarded-for") ?? "::1",
query,
Expand Down
18 changes: 17 additions & 1 deletion packages/open-next/src/overrides/converters/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,28 @@ import { extractHostFromHeaders, getQueryFromSearchParams } from "./utils.js";
const converter: Converter = {
convertFrom: async (req: IncomingMessage & { protocol?: string }) => {
const body = await new Promise<Buffer>((resolve) => {
const contentLength = req.headers["content-length"];
const expectedLength = contentLength
? Number.parseInt(contentLength, 10)
: undefined;
const chunks: Uint8Array[] = [];
let receivedLength = 0;

req.on("data", (chunk) => {
chunks.push(chunk);
receivedLength += chunk.length;
});
req.on("end", () => {
resolve(Buffer.concat(chunks));
// Use pre-allocated buffer if we have content-length and it matches
if (
expectedLength &&
receivedLength === expectedLength &&
chunks.length === 1
) {
resolve(Buffer.from(chunks[0]));
} else {
resolve(Buffer.concat(chunks));
}
});
});

Expand Down
Loading