// src/adapter/aws-lambda/handler.ts import crypto from "crypto"; import { encodeBase64 } from "../../utils/encode.js"; globalThis.crypto ??= crypto; var getRequestContext = (event) => { return event.requestContext; }; var streamToNodeStream = async (reader, writer) => { let readResult = await reader.read(); while (!readResult.done) { writer.write(readResult.value); readResult = await reader.read(); } writer.end(); }; var streamHandle = (app) => { return awslambda.streamifyResponse( async (event, responseStream, context) => { const processor = getProcessor(event); try { const req = processor.createRequest(event); const requestContext = getRequestContext(event); const res = await app.fetch(req, { event, requestContext, context }); const httpResponseMetadata = { statusCode: res.status, headers: Object.fromEntries(res.headers.entries()) }; responseStream = awslambda.HttpResponseStream.from(responseStream, httpResponseMetadata); if (res.body) { await streamToNodeStream(res.body.getReader(), responseStream); } else { responseStream.write(""); } } catch (error) { console.error("Error processing request:", error); responseStream.write("Internal Server Error"); } finally { responseStream.end(); } } ); }; var handle = (app) => { return async (event, lambdaContext) => { const processor = getProcessor(event); const req = processor.createRequest(event); const requestContext = getRequestContext(event); const res = await app.fetch(req, { event, requestContext, lambdaContext }); return processor.createResult(event, res); }; }; var EventProcessor = class { createRequest(event) { const queryString = this.getQueryString(event); const domainName = event.requestContext && "domainName" in event.requestContext ? event.requestContext.domainName : event.headers?.["host"] ?? event.multiValueHeaders?.["host"]?.[0]; const path = this.getPath(event); const urlPath = `https://${domainName}${path}`; const url = queryString ? `${urlPath}?${queryString}` : urlPath; const headers = new Headers(); this.getCookies(event, headers); if (event.headers) { for (const [k, v] of Object.entries(event.headers)) { if (v) { headers.set(k, v); } } } if (event.multiValueHeaders) { for (const [k, values] of Object.entries(event.multiValueHeaders)) { if (values) { const foundK = headers.get(k); values.forEach((v) => (!foundK || !foundK.includes(v)) && headers.append(k, v)); } } } const method = this.getMethod(event); const requestInit = { headers, method }; if (event.body) { requestInit.body = event.isBase64Encoded ? Buffer.from(event.body, "base64") : event.body; } return new Request(url, requestInit); } async createResult(event, res) { const contentType = res.headers.get("content-type"); let isBase64Encoded = contentType && isContentTypeBinary(contentType) ? true : false; if (!isBase64Encoded) { const contentEncoding = res.headers.get("content-encoding"); isBase64Encoded = isContentEncodingBinary(contentEncoding); } const body = isBase64Encoded ? encodeBase64(await res.arrayBuffer()) : await res.text(); const result = { body, headers: {}, statusCode: res.status, isBase64Encoded }; this.setCookies(event, res, result); res.headers.forEach((value, key) => { result.headers[key] = value; }); return result; } setCookies = (event, res, result) => { if (res.headers.has("set-cookie")) { const cookies = res.headers.get("set-cookie")?.split(", "); if (Array.isArray(cookies)) { this.setCookiesToResult(result, cookies); res.headers.delete("set-cookie"); } } }; }; var v2Processor = new class EventV2Processor extends EventProcessor { getPath(event) { return event.rawPath; } getMethod(event) { return event.requestContext.http.method; } getQueryString(event) { return event.rawQueryString; } getCookies(event, headers) { if (Array.isArray(event.cookies)) { headers.set("Cookie", event.cookies.join("; ")); } } setCookiesToResult(result, cookies) { result.cookies = cookies; } }(); var v1Processor = new class EventV1Processor extends EventProcessor { getPath(event) { return event.path; } getMethod(event) { return event.httpMethod; } getQueryString(event) { return Object.entries(event.queryStringParameters || {}).filter(([, value]) => value).map(([key, value]) => `${key}=${value}`).join("&"); } getCookies(event, headers) { } setCookiesToResult(result, cookies) { result.multiValueHeaders = { "set-cookie": cookies }; } }(); var getProcessor = (event) => { if (isProxyEventV2(event)) { return v2Processor; } else { return v1Processor; } }; var isProxyEventV2 = (event) => { return Object.prototype.hasOwnProperty.call(event, "rawPath"); }; var isContentTypeBinary = (contentType) => { return !/^(text\/(plain|html|css|javascript|csv).*|application\/(.*json|.*xml).*|image\/svg\+xml.*)$/.test( contentType ); }; var isContentEncodingBinary = (contentEncoding) => { if (contentEncoding === null) { return false; } return /^(gzip|deflate|compress|br)/.test(contentEncoding); }; export { getProcessor, handle, isContentEncodingBinary, isContentTypeBinary, streamHandle };