我有一个配置了多个来源的 CloudFront 分发,包括一个 API 网关部署。
我正在尝试在 CloudFront 上创建一个行为,以便任何收到的/api/*
路径请求都将被重定向到 API 网关,我所做的只是创建一个新的行为,其路径模式为,/api/*
Origin 为我提到的 API 网关部署。这可行,但是任何包含查询字符串的请求(例如/api/data?since=2020-01-01
)都会导致向 API 网关发出没有查询字符串的请求,即到达 API 网关的只是/api/data
。
为了解决这个问题,我尝试设置缓存策略为Managed-CachingOptimized
(甚至为Managed-CachingDisabled
) 和源请求策略为Managed-AllViewer
,但随后 CloudFront 开始完全忽略该行为并处理下一个行为,该行为恰好是 S3 存储桶。请求发送到 S3 存储桶后,我收到 404 返回,因为那里没有这样的密钥。
我也尝试使用“旧版缓存设置”,但同样的问题仍然存在。
是否可以使用 CloudFront 和 API GW 实现此“代理”?如果可以,我该怎么做?
谢谢
答案1
这也让我感到困惑,查询字符串和标头都如此,例如Authorization
。
但是,文档指出要将Authorization
标头传递到原点,必须将其用作缓存键:
缓存键设置指定 CloudFront 在缓存键中包含的查看器请求中的值。这些值可以包括 URL 查询字符串、HTTP 标头和 Cookie。包含在缓存键中的值会自动包含在 CloudFront 发送到源的请求(称为源请求)中。
和
注意:您不能使用源请求策略来转发授权标头。标头必须是缓存键的一部分,以防止缓存满足未经授权的请求。如果您尝试创建转发授权标头的源请求策略,CloudFront 将返回 HTTP 400 错误。
此外,请注意,与来源请求策略相关Managed-AllViewer
,问题似乎是将Host
标头转发到 API 网关;请参阅https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/571#issuecomment-792051286即我们不能将其用于Managed-AllViewer
API 网关来源。
看
- https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html
- https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-authorization-header/
作为 CDKcloudfront.Distribution()
构造的一部分:
const apiCachePolicy = new cloudfront.CachePolicy(this, 'ApiCachePolicy', {
headerBehavior: cloudfront.CacheHeaderBehavior.allowList('authorization'),
queryStringBehavior: cloudfront.CacheQueryStringBehavior.all(),
cookieBehavior: cloudfront.CacheCookieBehavior.none(),
minTtl: Duration.minutes(0),
maxTtl: Duration.minutes(1),
defaultTtl: Duration.minutes(0),
enableAcceptEncodingGzip: true,
enableAcceptEncodingBrotli: true,
});
答案2
我有一个类似的要求,即通过 cloudfront 访问 AWS GW 上的几个 API。
- 首先,我创建了几个带有路径变量的 API,例如用于 PUT 和 GET 方法的 /users/{users-id}
- 在 API GW 中创建自定义域(使用子域和 SSL 证书)并创建 API 映射(一个 API 映射到 asset1,另一个 API 映射到 asset2)
- 创建自定义原点作为 api 自定义域,如 api.xyz.com,并创建自定义映射路径 asset1 的行为以重定向到该 API
- 后端 API 在 ecs 容器上运行,我将其映射为 API GW 中的目标
- 然后能够通过来自 cloudfront 的根域代理该 API,并使用带有资源路径(如“http:///asset1/users/{user-id}”)的映射名称调用 API,方法是将用户 ID 替换为所需值。
但不幸的是,我无法从 cloudfront 实现 /api/* 映射,因为它期望 api 路径必须存在于 API GW 上,而 API GW 不支持使用自定义域的 api/asset1 等多级映射。