如何配置 CF 来解决此问题?
在API网关(APIG)通过其内部使用CloudFront(CF)支持边缘缓存之前,我想出了一个解决方法。
确实可以将CF分发放在APIG的前面,窍门是强制使用"Viewer Protocol Policy"的HTTPS only选项并且不要转发HOST标头,因为APIG需要SNI。
我将我的CF的"默认缓存行为设置"设置为不转发任何标头,并强制使用"Viewer Protocol Policy"的"HTTPS Only"选项。它有效了。希望这能帮助其他人。
以下是一个CloudFormation资源对象,它具有所有所需的配置(注意:我使用<stage>--<app name>
约定作为StackName):
CloudFront:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
IPV6Enabled: true
HttpVersion: http2
Comment: !Join [ '--', [!Ref 'AWS::StackName', ' Cloud Front']]
Aliases: [!Ref CloudFrontCname]
ViewerCertificate:
AcmCertificateArn: !Ref AcmCertificateArn
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.1_2016
Origins:
- Id: APIGOrigin
DomainName: !Sub
- ${apigId}.execute-api.${AWS::Region}.amazonaws.com
- { apigId: !Ref ApiGatewayLambdaProxy }
OriginPath: !Sub
- /${Stage}
- { Stage: !Select [ "0", !Split [ '--', !Ref 'AWS::StackName' ] ] }
CustomOriginConfig:
# HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginCustomHeaders:
- HeaderName: 'Verify-From-Cf'
HeaderValue: !Ref VerifyFromCfHeaderVal
DefaultCacheBehavior:
AllowedMethods: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
CachedMethods: ["GET", "HEAD", "OPTIONS"]
ForwardedValues:
Headers:
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Origin
- Authorization
# - Host APIG needs to use SNI
QueryString: true
TargetOriginId: APIGOrigin
ViewerProtocolPolicy: https-only
Compress: true
DefaultTTL: 0
CustomErrorResponses:
- ErrorCachingMinTTL: 0
ErrorCode: 400
- ErrorCachingMinTTL: 1
ErrorCode: 403
- ErrorCachingMinTTL: 5
ErrorCode: 500
DNSARecord:
Type: AWS::Route53::RecordSet
Properties:
Comment: !Ref 'AWS::StackName'
Name: !Ref CloudFrontCname
Type: A
HostedZoneName: !Join ['.', [ !Select [1, !Split ['.', !Ref CloudFrontCname]], !Select [2, !Split ['.', !Ref CloudFrontCname]], '']]
AliasTarget:
HostedZoneId: !Ref Route53HostedZoneId
DNSName: !GetAtt CloudFront.DomainName
DNSAAAARecord:
Type: AWS::Route53::RecordSet
Properties:
Comment: !Ref 'AWS::StackName'
Name: !Ref CloudFrontCname
Type: AAAA
HostedZoneName: !Join ['.', [ !Select [1, !Split ['.', !Ref CloudFrontCname]], !Select [2, !Split ['.', !Ref CloudFrontCname]], '']]
AliasTarget:
HostedZoneId: !Ref Route53HostedZoneId
DNSName: !GetAtt C
2018年末的更新
MinimumProtocolVersion:TLSv1.1_2016
补充之前的回答:
行为路径模式必须与“真实”路径匹配是非常重要的。
如果API终端节点是<id>.execute-api.<region>.amazonaws.com/stage-name/my-api
,
而原始域+路径是<id>.execute-api.<region>.amazonaws.com/stage-name
,
则行为路径模式必须是my-api
、my-api/*
、my-api/something
等。
我不知道为什么,但我认为路径模式可以用作别名,例如:
https://www.example.com/random-name(路径模式random-name
)解析为在源中设置的域+路径,例如<id>.execute-api.<region>.amazonaws.com/stage-name
。
但事实并非如此。
<id>.execute-api.<region>.amazonaws.com/stage-name/api/endpoint1
,源+路径:<id>.execute-api.<region>.amazonaws.com/stage-name
,路径模式:/api/*
,最终端点:https://<id>.cloudfront.net/api/endpoint1
,虽然与此无关,但我也发现这个回答对于传递标头非常有用:https://dev59.com/i6bja4cB1Zd3GeqPnN80#47380572 - Cadell Christo也可能是由于原始终端点不正确所致。"API Gateway将所有对不存在路径的错误视为403权限被拒绝错误,而不是404未找到错误。"(参见支持线程)。Authorization header requires 'Credential' parameter. Authorization header requires 'Signature' parameter. Authorization header requires 'SignedHeaders' parameter. Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header.
随着2017年11月API Gateway区域端点的推出,我相信现在最优的做法是在其上使用CloudFront分发。有关从边缘优化API转移到区域API并设置CloudFront分发的详细说明,请参见:
你可以使用CloudFront的行为和源特性。
例如,有多个源,如S3存储桶和另一个API网关。
然后根据行为将路由到特定的源。
像默认(*)行为将指向S3。
/api/*行为将指向API网关。
https://kuchbhilearning.blogspot.com/2022/10/add-cloudfront-behavior-and-origin.html代码。
更详细的解释https://kuchbhilearning.blogspot.com/2022/10/api-gateway-and-cloud-front-in-same.html