The current lambda implementation is 3 years old and only supports api gateway v1. Api gateway v2 is the standard now. Adding Api gateway v2 also unlocks Lambda Function URL support as they use the same handler type signature.
Not a breaking change.
Here is the implementation based on the v1.
// grafserv/lambda/v2/index.ts
import type {
APIGatewayProxyEventV2,
APIGatewayProxyHandlerV2,
APIGatewayProxyResultV2,
Context as LambdaContext,
} from "aws-lambda";
import type { GrafservConfig, RequestDigest, Result } from "grafserv";
import { GrafservBase } from "grafserv";
declare global {
namespace Grafast {
interface RequestContext {
lambdav2: { event: APIGatewayProxyEventV2; context: LambdaContext };
}
}
}
/** @experimental */
export class LambdaV2Grafserv extends GrafservBase {
protected lambdaRequestToGrafserv(
event: APIGatewayProxyEventV2,
context: LambdaContext,
): RequestDigest {
const version = event.requestContext.http.protocol.match(
/^HTTP\/(?<major>[0-9]+)\.(?<minor>[0-9]+)$/,
);
return {
httpVersionMajor: parseInt(version?.groups?.major ?? "1", 10),
httpVersionMinor: parseInt(version?.groups?.minor ?? "0", 10),
isSecure: false, // Because we don't trust X-Forwarded-Proto
method: event.requestContext.http.method,
path: event.rawPath,
headers: event.headers as Record<string, string>,
getQueryParams() {
return Object.fromEntries(
Object.entries(event.queryStringParameters ?? {}).filter(
([_k, v]) => v !== undefined,
),
) as Record<string, string>;
},
getBody() {
return {
type: "text",
text: event.body ?? "",
};
},
requestContext: {
lambdav2: { event, context },
},
preferJSON: true,
};
}
protected grafservResponseToLambda(
response: Result | null,
): APIGatewayProxyResultV2 {
if (response === null) {
return {
statusCode: 404,
body: "¯\\_(ツ)_/¯",
};
}
switch (response.type) {
case "error": {
const { statusCode, headers, error } = response;
return {
statusCode,
headers: { ...headers, "Content-Type": "text/plain" },
body: error.message,
};
}
case "buffer": {
const { statusCode, headers, buffer } = response;
return { statusCode, headers, body: buffer.toString("utf8") };
}
case "json": {
const { statusCode, headers, json } = response;
return { statusCode, headers, body: JSON.stringify(json) };
}
default: {
console.log("Unhandled:");
console.dir(response);
return {
statusCode: 501,
headers: { "Content-Type": "text/plain" },
body: "Server hasn't implemented this yet",
};
}
}
}
createHandler(): APIGatewayProxyHandlerV2<APIGatewayProxyResultV2> {
return async (
event: APIGatewayProxyEventV2,
context: LambdaContext,
): Promise<APIGatewayProxyResultV2> => {
return this.grafservResponseToLambda(
await this.processLambdaRequest(
event,
context,
this.lambdaRequestToGrafserv(event, context),
),
);
};
}
protected processLambdaRequest(
_event: APIGatewayProxyEventV2,
_context: LambdaContext,
request: RequestDigest,
) {
return this.processRequest(request);
}
}
/** @experimental */
export function grafserv(config: GrafservConfig) {
return new LambdaV2Grafserv(config);
}
Feature description
The current lambda implementation is 3 years old and only supports api gateway v1. Api gateway v2 is the standard now. Adding Api gateway v2 also unlocks Lambda Function URL support as they use the same handler type signature.
Breaking changes
Not a breaking change.
Supporting development
Here is the implementation based on the v1.