使用无服务器的 WebSockets API 的自定义域名
Custom Domain Name for WebSockets API with Serverless
我正在为一个无服务器应用程序管理 REST API,并希望在同一区域使用 WebSockets API 扩展此设置。一切都应该使用相同的证书处理,但子域不同。
起初我用 sls create_domain --stage=...
创建了一个新的自定义域。
然后我尝试将它添加到新的 WebSockets 堆栈,但以这个错误结束:
Error: Failed to find CloudFormation resources for ...
我在 Github 上发现 CloudFormation 现在似乎不支持它,因此 Serverless 不支持它。
所以我尝试在 UI:
中手动将我的舞台附加到自定义域名
Mixing of REST APIs and HTTP APIs on the same domain name can only be
accomplished through API Gateway's V2 DomainName interface. Currently,
WebSocket APIs can only be attached to a domain name with other
WebSocket APIs. This must also occur through API Gateway's V2
DomainName interface.
更多的混乱出现了,因为在这种情况下它甚至不是同一个域名。新域名为 sockets.<DOMAIN>.com
,现有域名为 api.<DOMAIN>.com
。或者不同的子域是否属于 'same domain name'?
尽管如此,我还是尝试通过 apigatewayv2 CLI 再次创建自定义域:
aws apigatewayv2 create-domain-name --domain-name <DOMAIN> --domain-name-configurations file://domain-configuration.json --region eu-west-1
域-configuration.json:
[
{
"ApiGatewayDomainName": "<DOMAIN>",
"CertificateArn": "arn:aws:acm:us-east-1:<ACCOUNT_ID>:certificate/<CERT_ID>",
"CertificateName": "<DOMAIN>",
"DomainNameStatus": "AVAILABLE",
"EndpointType": "EDGE",
"SecurityPolicy": "TLS_1_2"
}
]
但这会导致以下错误:
An error occurred (BadRequestException) when calling the CreateDomainName operation: Invalid certificate ARN: arn:aws:acm:us-east-1:924441585974:certificate/b88f0a3f-1393-4a16-a876-9830852b5207. Certificate must be in 'eu-west-1'.
我目前的状态是 API 网关只允许自定义证书位于 us-east-1,所以这个错误让我更加困惑。
总结:我完全不知道如何将自定义域名附加到我的 WebSocket API 阶段。我很高兴每一个正确方向的提示!
找到了具有自定义 CloudFormation 资源模板的解决方案:
resources:
Resources:
WebSocketDomainName:
Type: AWS::ApiGatewayV2::DomainName
Properties:
DomainName: <domain-name>
DomainNameConfigurations:
- EndpointType: 'REGIONAL'
CertificateArn: <cert-arn>
WebSocketMapping:
Type: AWS::ApiGatewayV2::ApiMapping
Properties:
ApiId: <api-id>
DomainName: !Ref WebSocketDomainName
Stage: <stage-name>
DNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: <hosted-zone-name>.
TTL: '900'
ResourceRecords:
- !GetAtt [ WebSocketDomainName, RegionalDomainName ]
Name: <domain-name>
Type: CNAME
编辑:现在正在使用 serverless-domain-manager!
custom:
customDomain:
rest:
domainName: rest.serverless.foo.com
stage: ci
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
http:
domainName: http.serverless.foo.com
stage: ci
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
websocket:
domainName: ws.serverless.foo.com
stage: ci
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
感谢@tpschmidt 的有用回复!
只需添加,如果您想要 BasePathMapping 用于您的 websocket 域,请将 ApiMapping Key 添加到上面提供的 Cloudformation。例如:
WebSocketMapping:
Type: AWS::ApiGatewayV2::ApiMapping
Properties:
ApiId: <api-id>
DomainName: !Ref WebSocketDomainName
Stage: <stage-name>
ApiMappingKey: <stage-name> #(e.g. prod)
我不得不进行一些小的调整,以便在具有 WebSockets 支持和自定义域的私有 VPC 中使用 Lambda。
CertificateArn
必须来自 ACM,不能 是上传到 IAM 的证书。
- 我使用了 A 记录而不是 CNAME
WebSocketDomainName:
Type: AWS::ApiGatewayV2::DomainName
Properties:
DomainName: !Ref DomainName
DomainNameConfigurations:
- EndpointType: REGIONAL
CertificateArn: <your-certificate-arn>
# This maps /staging or /prod to just the domain name
WebSocketMapping:
Type: AWS::ApiGatewayV2::ApiMapping
Properties:
ApiId: <your-api-id>
DomainName: !Ref WebSocketDomainName
Stage: <your-stage>
Route53DNS:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneName: !Ref Route53HostedZone
RecordSets:
- Name: !Ref DomainName
Type: A
AliasTarget:
HostedZoneId: ZLY8HYME6SFDD # This means eu-west-1 ApiGateWay
DNSName:
!GetAtt [WebSocketDomainName, RegionalDomainName]
您的 HostedZoneId
检查:https://docs.aws.amazon.com/general/latest/gr/apigateway.html
我正在为一个无服务器应用程序管理 REST API,并希望在同一区域使用 WebSockets API 扩展此设置。一切都应该使用相同的证书处理,但子域不同。
起初我用 sls create_domain --stage=...
创建了一个新的自定义域。
然后我尝试将它添加到新的 WebSockets 堆栈,但以这个错误结束:
Error: Failed to find CloudFormation resources for ...
我在 Github 上发现 CloudFormation 现在似乎不支持它,因此 Serverless 不支持它。
所以我尝试在 UI:
中手动将我的舞台附加到自定义域名Mixing of REST APIs and HTTP APIs on the same domain name can only be accomplished through API Gateway's V2 DomainName interface. Currently, WebSocket APIs can only be attached to a domain name with other WebSocket APIs. This must also occur through API Gateway's V2 DomainName interface.
更多的混乱出现了,因为在这种情况下它甚至不是同一个域名。新域名为 sockets.<DOMAIN>.com
,现有域名为 api.<DOMAIN>.com
。或者不同的子域是否属于 'same domain name'?
尽管如此,我还是尝试通过 apigatewayv2 CLI 再次创建自定义域:
aws apigatewayv2 create-domain-name --domain-name <DOMAIN> --domain-name-configurations file://domain-configuration.json --region eu-west-1
域-configuration.json:
[
{
"ApiGatewayDomainName": "<DOMAIN>",
"CertificateArn": "arn:aws:acm:us-east-1:<ACCOUNT_ID>:certificate/<CERT_ID>",
"CertificateName": "<DOMAIN>",
"DomainNameStatus": "AVAILABLE",
"EndpointType": "EDGE",
"SecurityPolicy": "TLS_1_2"
}
]
但这会导致以下错误:
An error occurred (BadRequestException) when calling the CreateDomainName operation: Invalid certificate ARN: arn:aws:acm:us-east-1:924441585974:certificate/b88f0a3f-1393-4a16-a876-9830852b5207. Certificate must be in 'eu-west-1'.
我目前的状态是 API 网关只允许自定义证书位于 us-east-1,所以这个错误让我更加困惑。
总结:我完全不知道如何将自定义域名附加到我的 WebSocket API 阶段。我很高兴每一个正确方向的提示!
找到了具有自定义 CloudFormation 资源模板的解决方案:
resources:
Resources:
WebSocketDomainName:
Type: AWS::ApiGatewayV2::DomainName
Properties:
DomainName: <domain-name>
DomainNameConfigurations:
- EndpointType: 'REGIONAL'
CertificateArn: <cert-arn>
WebSocketMapping:
Type: AWS::ApiGatewayV2::ApiMapping
Properties:
ApiId: <api-id>
DomainName: !Ref WebSocketDomainName
Stage: <stage-name>
DNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: <hosted-zone-name>.
TTL: '900'
ResourceRecords:
- !GetAtt [ WebSocketDomainName, RegionalDomainName ]
Name: <domain-name>
Type: CNAME
编辑:现在正在使用 serverless-domain-manager!
custom:
customDomain:
rest:
domainName: rest.serverless.foo.com
stage: ci
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
http:
domainName: http.serverless.foo.com
stage: ci
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
websocket:
domainName: ws.serverless.foo.com
stage: ci
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
感谢@tpschmidt 的有用回复! 只需添加,如果您想要 BasePathMapping 用于您的 websocket 域,请将 ApiMapping Key 添加到上面提供的 Cloudformation。例如:
WebSocketMapping:
Type: AWS::ApiGatewayV2::ApiMapping
Properties:
ApiId: <api-id>
DomainName: !Ref WebSocketDomainName
Stage: <stage-name>
ApiMappingKey: <stage-name> #(e.g. prod)
我不得不进行一些小的调整,以便在具有 WebSockets 支持和自定义域的私有 VPC 中使用 Lambda。
CertificateArn
必须来自 ACM,不能 是上传到 IAM 的证书。- 我使用了 A 记录而不是 CNAME
WebSocketDomainName:
Type: AWS::ApiGatewayV2::DomainName
Properties:
DomainName: !Ref DomainName
DomainNameConfigurations:
- EndpointType: REGIONAL
CertificateArn: <your-certificate-arn>
# This maps /staging or /prod to just the domain name
WebSocketMapping:
Type: AWS::ApiGatewayV2::ApiMapping
Properties:
ApiId: <your-api-id>
DomainName: !Ref WebSocketDomainName
Stage: <your-stage>
Route53DNS:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneName: !Ref Route53HostedZone
RecordSets:
- Name: !Ref DomainName
Type: A
AliasTarget:
HostedZoneId: ZLY8HYME6SFDD # This means eu-west-1 ApiGateWay
DNSName:
!GetAtt [WebSocketDomainName, RegionalDomainName]
您的 HostedZoneId
检查:https://docs.aws.amazon.com/general/latest/gr/apigateway.html