![](/img/trans.png)
[英]How to debug in VS Code a local AWS Lambda function with API Gateway written in TypeScript?
[英]How to use AWS Websocket API Gateway Lambda endpoint callback function
当客户端向 AWS websocket API Gateway 发送 websocket 消息时,websocket Lambda 处理程序函数接收三个参数: event
、 context
和callback
:
import type { APIGatewayProxyEvent, Context, } from "aws-lambda";
export class Handler {
constructor() {}
async execute(event: APIGatewayProxyEvent, context: Context, callback: any): Promise<void> {
console.log(`${event}, ${context}, ${callback}`);
if (!event.requestContext || !event.requestContext.connectionId) {
callback(null, { statusCode: 400, body: "Missing RequestContext" });
};
callback(null, {statusCode: 200, body: 'Your message was received'});
}
}
const Handler = new Handler(service);
async function handler(event: APIGatewayProxyEvent, context: Context, callback: any): Promise<void> {
return await Handler.execute(event, context, callback);
}
export default handler;
处理程序检查它收到的event
是否包含event.requestContext.connectionId
的值。 如果没有,它调用回调函数传递null
作为第一个参数和一条包含 400 statusCode
和body
的消息,其中消息告诉 connectionId 丢失:
callback(null, { statusCode: 400, body: "Missing RequestContext" });
不幸的是,我找不到任何描述我们应该如何使用这个callback
函数的 AWS 文档。 相反,我使用了一些在 Internet 上找到的代码示例。
我期待调用callback
函数并传递400 status
将使 Handler 函数退出并引发异常。 但它不会发生。 处理程序只是继续执行下一行,就像什么都没发生一样,并且从未调用过回调函数。
callback
函数的真正目的是什么?请将您的答案作为脚本示例或片段发布,以便我们对其进行测试。
PS 发布在https://aws.amazon.com/blogs/compute/announcing-websocket-apis-in-amazon-api-gateway/的文档说:
The backend can send messages to specific users via a callback URL that is provided after the user is connected to the WebSocket API.
并且有一个片段显示它:
exports.handler = function(event, context, callback) {
var putParams = {
TableName: process.env.TABLE_NAME,
Item: {
connectionId: { S: event.requestContext.connectionId }
}
};
DDB.putItem(putParams, function(err, data) {
callback(null, {
statusCode: err ? 500 : 200,
body: err ? "Failed to connect: " + JSON.stringify(err) : "Connected"
});
});
};
关于使用 Websocket API 的 Lambda 集成的双向通信模式,有一些重要的事情需要了解:
“回调”是一个重载的术语。 首先,它指的是 Nodejs Lambda 函数处理程序的遗留模式。 我们应该考虑到这一点,以支持AWS 推荐的async-await 处理程序模式。 其次,AWS 有时将“回调 URL”称为后端使用@aws-sdk/client-apigatewaymanagementapi客户端1与 Websocket 客户端通信的方式。 文档还提到与@connections commands相同的东西。
您的代码的一个问题是您混淆了不相关的 Lambda 和 Websocket API“回调”概念。 为避免歧义,我将完全避免使用“回调”一词。
有两种方法可以将数据从后端服务发送到连接的客户端:
$default
路由集成响应与RouteResponse
仅对于$default
路由,您的 Lambda 可以在处理程序响应中向客户端返回一条消息。 这仅在您将RouteResponse添加到路线2时才有效。
// default-route-handler.ts
import { APIGatewayProxyWebsocketEventV2 } from 'aws-lambda';
interface TwoWayHandlerResponse {
statusCode: 200 | 500;
body: string;
}
export async function handler(event: APIGatewayProxyWebsocketEventV2): Promise<TwoWayHandlerResponse> {
return {
statusCode: 200,
body: JSON.stringify('hello client, I am the $default route!'),
};
}
对于所有路由,您可以使用 @connections API 发送 POST 请求。 使用ApiGatewayManagementApi客户端的PostToConnection
API 执行此操作,该 API 处理将消息发送到客户端的繁重工作。 Lambda 只是返回一个状态。
// another-great-handler.ts
import { APIGatewayProxyWebsocketEventV2 } from 'aws-lambda';
import { ApiGatewayManagementApiClient, PostToConnectionCommand } from '@aws-sdk/client-apigatewaymanagementapi';
interface StatusCodeResponse {
statusCode: 200 | 500;
}
export async function handler(event: APIGatewayProxyWebsocketEventV2): Promise<StatusCodeResponse> {
const { requestContext: { domainName, stage, connectionId, connectedAt, routeKey },} = event;
try {
const client = new ApiGatewayManagementApiClient({
region: process.env.AWS_REGION,
endpoint: 'https://' + domainName + '/' + stage,
});
const encoder = new TextEncoder();
const postCmd = new PostToConnectionCommand({
ConnectionId: connectionId,
Data: encoder.encode(`Hello from ${routeKey}. You connected at: ${connectedAt}`),
});
await client.send(postCmd);
} catch (err: unknown) {
return { statusCode: 500 };
}
return { statusCode: 200 };
}
我正在使用AWS JS SDK v3
在控制台中添加一个 RouteResponse( $default
route >“添加集成响应”按钮),或者使用create-route-response API,或者使用CloudFormation AWS::ApiGatewayV2::RouteResponse
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.