提问者:小点点

为什么我的API网关WebSocket没有配置自定义域名发送响应?


我已经用API网关配置了一个WebSocketAPI,并试图为它配置一个自定义域名。这是一个非常简单的API,用于在连接的客户端之间发送消息,它将连接ID存储在DynamoDB中。本质上,它类似于这里演示的示例:https://aws.amazon.com/blogs/compute/announcing-websocket-apis-in-amazon-api-gateway/

当使用AWS生成的URL即wss://时,所有工作都很好。execute-api.us-west-2.amazonaws.com/.但是,当我按照AWS的这些说明设置自定义区域域名时,我能够连接,但无法在客户端之间发送消息。

我已经检查了我的Lambda函数的Cloudwatch日志,没有看到任何错误,并且尝试使用我的Cloud地层模板启动一个全新的环境,但没有成功。

非常清楚地说,以下连接命令正确触发了我的Lambda函数,并在Route 53中使用AWS生成的URL和我自己的连接我的客户端。

wscat -c wss://<endpoint> <payload>

以下命令向连接的客户端发送消息,使用AWS生成的URL,但不是我自己的。

{ "message": "sendMessage", "toId": "193818", "data", "a random msg" }

共3个答案

匿名用户

我们遇到了同样的问题,但是api返回了一个错误:

botocore.errorfactory.ForbiddenException: An error occurred (ForbiddenException) when calling the PostToConnection operation: Forbidden

我们最终手动构造了用于发送回响应的回调url:{api_id}. exate-api.{region}.amazonaws.com

您可以从传递给lambda函数的请求上下文中获取api id。

我们使用的python/boto3代码:

stage = event['requestContext']['stage']
api_id = event['requestContext']['apiId']
region = 'us-east-1'

domain = f'{api_id}.execute-api.{region}.amazonaws.com'
client = boto3.client('apigatewaymanagementapi', endpoint_url=f'https://{domain}/{stage}')

client.post_to_connection(
    Data='...',
    ConnectionId='...'
)

匿名用户

当您使用AWS生成的URL即wss://时execute-api.us-west-2.amazonaws.com/您需要在URL后添加阶段名称,即wss://aws-Generatedurl/prod。

但是您必须忽略自定义域中的阶段名称。您可以使用简单的if-else来处理此问题。

let endPointName;
let domainName = event.requestContext.domainName;
let stageName = event.requestContext.stage;

if (domainName=='mydomain.com') {
  endPointName = domainName
}
else {
  endPointName = domainName + '/' + stageName;
}

const apigwManagementApi = new AWS.ApiGatewayManagementApi({
  apiVersion: '2018-11-29',
  endpoint: endPointName
});

匿名用户

这可能有点晚了。这是因为在使用postToConnection时,aws-sdk(AWS. ApiGatewayManagementApi)尝试仅使用其内部资源(在这种情况下AWS生成的URL)解析endpoint。AWSSDK不知道外部资源(在这种情况下是您的自定义域)。因此,它适用于AWS生成的URL,而不是您的自定义URL。如果您想在后面的代码中处理此问题,那么您可能需要创建一个字典,将您的自定义URL映射到AWS生成的URL。作为替代方案,创建一个web-socket客户端(非aws-skd)并传递您的自定义URL。我个人没有使用第二种使用web-socket客户端的方法,但我相信它应该可以工作。