我目前正在开发 Spring 应用程序,并在尝试将消息发布到 Websocket 连接时遇到问题。
我已在 AWS API Gateway 中成功设置 Websocket API,并且可以通过 Postman 使用我的 IAM 凭证发布到特定连接。
但是,当我尝试在 Spring 应用程序中使用 Java AWS SDK 执行相同操作时,我收到 403 错误。
这是 Spring 中的代码片段:
AwsSessionCredentials awsCreds = AwsSessionCredentials.create(
"***********",
"*********",
"**********"
);
AwsCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(awsCreds);
ApiGatewayManagementApiClient testApiClient = ApiGatewayManagementApiClient.builder()
.region(Region.US_WEST_2)
.credentialsProvider(credentialsProvider)
.endpointOverride(new URI("https://api-id.execute-api.us-west-2.amazonaws.com/@connections/stage"))
.build();
String connectionId = "********";
GetConnectionResponse getResponse = testApiClient.getConnection(GetConnectionRequest.builder()
.connectionId(connectionId)
.build());
PostToConnectionResponse postResponse = testApiClient.postToConnection(PostToConnectionRequest.builder()
.connectionId(connectionId)
.data(SdkBytes.fromUtf8String("test message from Spring"))
.build());
第一个请求正在尝试获取有关连接的信息。
第二个请求正在尝试向连接发送消息。两者都会返回 403 错误。
我知道我的凭据具有正确的权限,因为我可以使用相同的凭据通过 Postman 直接发送相同的请求,并且它有效。
问题是什么?
TLDR:使用
endpointOverride
的
https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}
值
您无需在
@connections
中指定 endpointOverride
。
根据 Javadoc,SDK 端点覆盖遵循以下格式:
https://{api-id}.execute-api.{region}.amazonaws.com/{stage}
不是:
https://{api-id}.execute-api.{region}.amazonaws.com/@connections/{stage}
使用 SDK 时,
getConnection
和 postToConnection
方法(以及 deleteConnection
方法)将自动将 @connections
附加到已部署 API 的端点。
GetConnectionRequestMarshaller.class
:
@SdkInternalApi
public class GetConnectionRequestMarshaller implements Marshaller<GetConnectionRequest> {
// ...
static {
SDK_OPERATION_BINDING = OperationInfo
.builder()
.requestUri("/@connections/{connectionId}")
.httpMethod(SdkHttpMethod.GET)
.hasExplicitPayloadMember(false)
.hasImplicitPayloadMembers(false)
.hasPayloadMembers(false)
.build();
}
}
PostToConnectionRequestMarshaller.class
:
@SdkInternalApi
public class PostToConnectionRequestMarshaller implements Marshaller<PostToConnectionRequest> {
// ...
static {
SDK_OPERATION_BINDING = OperationInfo
.builder()
.requestUri("/@connections/{connectionId}")
.httpMethod(SdkHttpMethod.POST)
.hasExplicitPayloadMember(true)
.hasImplicitPayloadMembers(false)
.hasPayloadMembers(true)
.build();
}
}
这应该有效:
URI endpointOverride = new URI("https://api-id.execute-api.us-west-2.amazonaws.com/stage");
ApiGatewayManagementApiClient testApiClient =
ApiGatewayManagementApiClient
.builder()
.region(Region.US_WEST_2)
.credentialsProvider(credentialsProvider)
.endpointOverride()
.build();
即使您在没有 SDK 的情况下手动调用 API,记录格式为:
https://{api-id}.execute-api.{region}.amazonaws.com/{stage}/@connections/{connection_id}
/@connections/{stage}
根本不起作用。