Skip to content

Commit

Permalink
fix: swap lambda entries
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed May 16, 2024
1 parent 9c0cd51 commit e5832f1
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 140 deletions.
140 changes: 78 additions & 62 deletions src/presets/aws-lambda/runtime/aws-lambda-streaming.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,94 @@
import type {
APIGatewayProxyEvent,
APIGatewayProxyEventV2,
APIGatewayProxyResult,
APIGatewayProxyResultV2,
Context,
APIGatewayProxyStructuredResultV2,
} from "aws-lambda";
import "#internal/nitro/virtual/polyfill";
import { withQuery } from "ufo";
import { nitroApp } from "#internal/nitro/app";
import {
normalizeLambdaIncomingHeaders,
normalizeLambdaOutgoingBody,
normalizeLambdaOutgoingHeaders,
} from "#internal/nitro/utils.lambda";
import { normalizeCookieHeader } from "#internal/nitro/utils";

export async function handler(
event: APIGatewayProxyEvent,
context: Context
): Promise<APIGatewayProxyResult>;
export async function handler(
event: APIGatewayProxyEventV2,
context: Context
): Promise<APIGatewayProxyResultV2>;
export async function handler(
event: APIGatewayProxyEvent | APIGatewayProxyEventV2,
context: Context
): Promise<APIGatewayProxyResult | APIGatewayProxyResultV2> {
const query = {
...event.queryStringParameters,
...(event as APIGatewayProxyEvent).multiValueQueryStringParameters,
};
const url = withQuery(
(event as APIGatewayProxyEvent).path ||
(event as APIGatewayProxyEventV2).rawPath,
query
);
const method =
(event as APIGatewayProxyEvent).httpMethod ||
(event as APIGatewayProxyEventV2).requestContext?.http?.method ||
"get";
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace awslambda {
// https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html
function streamifyResponse(
handler: (
event: APIGatewayProxyEventV2,
responseStream: NodeJS.WritableStream,
context: Context
) => Promise<void>
): any;

if ("cookies" in event && event.cookies) {
event.headers.cookie = event.cookies.join(";");
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace HttpResponseStream {
function from(
stream: NodeJS.WritableStream,
metadata: {
statusCode: APIGatewayProxyStructuredResultV2["statusCode"];
headers: APIGatewayProxyStructuredResultV2["headers"];
}
): NodeJS.WritableStream;
}
}
}

const r = await nitroApp.localCall({
event,
url,
context,
headers: normalizeLambdaIncomingHeaders(event.headers) as Record<
string,
string | string[]
>,
method,
query,
body: event.isBase64Encoded
? Buffer.from(event.body || "", "base64").toString("utf8")
: event.body,
});
export const handler = awslambda.streamifyResponse(
async (event: APIGatewayProxyEventV2, responseStream, context) => {
const query = {
...event.queryStringParameters,
};
const url = withQuery(event.rawPath, query);
const method = event.requestContext?.http?.method || "get";

// ApiGateway v2 https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.v2
const isApiGwV2 = "cookies" in event || "rawPath" in event;
const awsBody = await normalizeLambdaOutgoingBody(r.body, r.headers);
const cookies = normalizeCookieHeader(r.headers["set-cookie"]);
return {
...(cookies.length > 0 && {
...(isApiGwV2
? { cookies }
: { multiValueHeaders: { "set-cookie": cookies } }),
}),
statusCode: r.status,
headers: normalizeLambdaOutgoingHeaders(r.headers, true),
body: awsBody.body,
isBase64Encoded: awsBody.type === "binary",
};
}
if ("cookies" in event && event.cookies) {
event.headers.cookie = event.cookies.join(";");
}

const r = await nitroApp.localCall({
event,
url,
context,
headers: normalizeLambdaIncomingHeaders(event.headers) as Record<
string,
string | string[]
>,
method,
query,
body: event.isBase64Encoded
? Buffer.from(event.body || "", "base64").toString("utf8")
: event.body,
});
const httpResponseMetadata = {
statusCode: r.status,
headers: {
...normalizeLambdaOutgoingHeaders(r.headers, true),
"Transfer-Encoding": "chunked",
},
};
if (r.body) {
const reader = r.body as ReadableStream;
const writer = awslambda.HttpResponseStream.from(
responseStream,
httpResponseMetadata
);
await streamToNodeStream(reader.getReader(), responseStream);
writer.end();
}
}
);

const streamToNodeStream = async (
reader: ReadableStreamDefaultReader<Uint8Array>,
writer: NodeJS.WritableStream
) => {
let readResult = await reader.read();
while (!readResult.done) {
writer.write(readResult.value);
readResult = await reader.read();
}
writer.end();
};
140 changes: 62 additions & 78 deletions src/presets/aws-lambda/runtime/aws-lambda.ts
Original file line number Diff line number Diff line change
@@ -1,94 +1,78 @@
import type {
APIGatewayProxyEvent,
APIGatewayProxyEventV2,
APIGatewayProxyResult,
APIGatewayProxyResultV2,
Context,
APIGatewayProxyStructuredResultV2,
} from "aws-lambda";
import "#internal/nitro/virtual/polyfill";
import { withQuery } from "ufo";
import { nitroApp } from "#internal/nitro/app";
import {
normalizeLambdaIncomingHeaders,
normalizeLambdaOutgoingBody,
normalizeLambdaOutgoingHeaders,
} from "#internal/nitro/utils.lambda";
import { normalizeCookieHeader } from "#internal/nitro/utils";

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace awslambda {
// https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html
function streamifyResponse(
handler: (
event: APIGatewayProxyEventV2,
responseStream: NodeJS.WritableStream,
context: Context
) => Promise<void>
): any;
export async function handler(
event: APIGatewayProxyEvent,
context: Context
): Promise<APIGatewayProxyResult>;
export async function handler(
event: APIGatewayProxyEventV2,
context: Context
): Promise<APIGatewayProxyResultV2>;
export async function handler(
event: APIGatewayProxyEvent | APIGatewayProxyEventV2,
context: Context
): Promise<APIGatewayProxyResult | APIGatewayProxyResultV2> {
const query = {
...event.queryStringParameters,
...(event as APIGatewayProxyEvent).multiValueQueryStringParameters,
};
const url = withQuery(
(event as APIGatewayProxyEvent).path ||
(event as APIGatewayProxyEventV2).rawPath,
query
);
const method =
(event as APIGatewayProxyEvent).httpMethod ||
(event as APIGatewayProxyEventV2).requestContext?.http?.method ||
"get";

// eslint-disable-next-line @typescript-eslint/no-namespace
namespace HttpResponseStream {
function from(
stream: NodeJS.WritableStream,
metadata: {
statusCode: APIGatewayProxyStructuredResultV2["statusCode"];
headers: APIGatewayProxyStructuredResultV2["headers"];
}
): NodeJS.WritableStream;
}
if ("cookies" in event && event.cookies) {
event.headers.cookie = event.cookies.join(";");
}
}

export const handler = awslambda.streamifyResponse(
async (event: APIGatewayProxyEventV2, responseStream, context) => {
const query = {
...event.queryStringParameters,
};
const url = withQuery(event.rawPath, query);
const method = event.requestContext?.http?.method || "get";

if ("cookies" in event && event.cookies) {
event.headers.cookie = event.cookies.join(";");
}

const r = await nitroApp.localCall({
event,
url,
context,
headers: normalizeLambdaIncomingHeaders(event.headers) as Record<
string,
string | string[]
>,
method,
query,
body: event.isBase64Encoded
? Buffer.from(event.body || "", "base64").toString("utf8")
: event.body,
});
const httpResponseMetadata = {
statusCode: r.status,
headers: {
...normalizeLambdaOutgoingHeaders(r.headers, true),
"Transfer-Encoding": "chunked",
},
};
if (r.body) {
const reader = r.body as ReadableStream;
const writer = awslambda.HttpResponseStream.from(
responseStream,
httpResponseMetadata
);
await streamToNodeStream(reader.getReader(), responseStream);
writer.end();
}
}
);
const r = await nitroApp.localCall({
event,
url,
context,
headers: normalizeLambdaIncomingHeaders(event.headers) as Record<
string,
string | string[]
>,
method,
query,
body: event.isBase64Encoded
? Buffer.from(event.body || "", "base64").toString("utf8")
: event.body,
});

const streamToNodeStream = async (
reader: ReadableStreamDefaultReader<Uint8Array>,
writer: NodeJS.WritableStream
) => {
let readResult = await reader.read();
while (!readResult.done) {
writer.write(readResult.value);
readResult = await reader.read();
}
writer.end();
};
// ApiGateway v2 https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.v2
const isApiGwV2 = "cookies" in event || "rawPath" in event;
const awsBody = await normalizeLambdaOutgoingBody(r.body, r.headers);
const cookies = normalizeCookieHeader(r.headers["set-cookie"]);
return {
...(cookies.length > 0 && {
...(isApiGwV2
? { cookies }
: { multiValueHeaders: { "set-cookie": cookies } }),
}),
statusCode: r.status,
headers: normalizeLambdaOutgoingHeaders(r.headers, true),
body: awsBody.body,
isBase64Encoded: awsBody.type === "binary",
};
}

0 comments on commit e5832f1

Please sign in to comment.