Skip to content
Open
Show file tree
Hide file tree
Changes from all 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/rude-dodos-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@opennextjs/aws": patch
---

Replaces delete usage with assignment operator to undefined to avoid going into slowest mode in objects
5 changes: 3 additions & 2 deletions packages/open-next/src/core/requestHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ export async function openNextHandler(
overwrittenResponseHeaders[key] = value;
}
headers[key] = value;
delete headers[rawKey];
// @ts-expect-error Setting it to undefined is faster than deleting the attribute.
headers[rawKey] = undefined;
}

if (
Expand Down Expand Up @@ -238,7 +239,7 @@ async function processRequest(
// @ts-ignore
// Next.js doesn't parse body if the property exists
// https://github.com/dougmoscrop/serverless-http/issues/227
delete req.body;
req.body = undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment above explicitely says "the property exists"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth an upstream pr to next.js tho I suspect it's been tried before.

The key challenge with using delete here is that it immediately puts req into a slower / non-optimized mode for all property accesses. Whether or not that moves the needle or not in performance depends on usage pattern. In this particular case, let's leave this as delete req.body and see if we can try to fix upstream.

but as a general rule, we should be avoiding delete like the plague.


// Here we try to apply as much request metadata as possible
// We apply every metadata from `resolve-routes` https://github.com/vercel/next.js/blob/916f105b97211de50f8580f0b39c9e7c60de4886/packages/next/src/server/lib/router-utils/resolve-routes.ts
Expand Down
3 changes: 2 additions & 1 deletion packages/open-next/src/core/routingHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ export default async function routingHandler(
key.startsWith(INTERNAL_HEADER_PREFIX) ||
key.startsWith(MIDDLEWARE_HEADER_PREFIX)
) {
delete event.headers[key];
// @ts-expect-error Assigning undefined is faster than deleting the attribute.
event.headers[key] = undefined;
}
}

Expand Down
6 changes: 1 addition & 5 deletions packages/open-next/src/http/openNextResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export class OpenNextNodeResponse extends Transform implements ServerResponse {
if (key === SET_COOKIE_HEADER) {
this._cookies = [];
} else {
delete this.headers[key];
this.headers[key] = undefined;
}
return this;
}
Expand Down Expand Up @@ -188,10 +188,6 @@ export class OpenNextNodeResponse extends Transform implements ServerResponse {

const parsedHeaders = parseHeaders(this.headers);

// We need to remove the set-cookie header from the parsed headers because
// it does not handle multiple set-cookie headers properly
delete parsedHeaders[SET_COOKIE_HEADER];

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this is removed but not replaced?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, I see, you're removing it in the util.ts change instead.

if (this.streamCreator) {
this.responseStream = this.streamCreator?.writeHeaders({
statusCode: this.statusCode ?? 200,
Expand Down
8 changes: 7 additions & 1 deletion packages/open-next/src/http/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ export const parseHeaders = (
continue;
}
const keyLower = key.toLowerCase();
if (keyLower === "set-cookie") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that a change in behavior?

// We need to remove the set-cookie header from the parsed headers because
// it does not handle multiple set-cookie headers properly
continue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

side note... I keep thinking that it would be nice if Object.entries(...) (and the iterable pattern in general) would accept a filter function...

Object.entries(headers, filter);

...that could optimize this pattern more and make it so the collection only had to be iterated through once... That's for another time tho.

}

/**
* Next can return an Array for the Location header when you return null from a get in the cacheHandler on a page that has a redirect()
* We dont want to merge that into a comma-separated string
Expand All @@ -22,7 +28,7 @@ export const parseHeaders = (
* See: https://github.com/opennextjs/opennextjs-cloudflare/issues/875#issuecomment-3258248276
* and https://github.com/opennextjs/opennextjs-aws/pull/977#issuecomment-3261763114
*/
if (keyLower === "location" && Array.isArray(value)) {
if (Array.isArray(value) && keyLower === "location") {
if (value[0] === value[1]) {
result[keyLower] = value[0];
} else {
Expand Down
Loading