更新:这个答案在编写时是正确的,下面描述的技术仍然是完全可行的,但可能不太理想,因为现在可以使用 Lambda@Edge 来实现这个目标,正如我在对 @987654321 的回答中所解释的那样@.
不,无法自动执行此操作。
有没有办法在不运行重定向服务器的情况下完成此操作?
从技术上讲,您不需要重定向来完成此操作。您需要路径重写,这就是为什么您的最终问题的答案是“否”——因为 Route 53(以及一般的 DNS)不能做任何与路径相关的事情。
Route 53 确实支持通配符 DNS,但如果 CloudFront 和/或 S3 不支持将主机标头从 HTTP 请求放入路径的机制(它们不支持),这将是有限的帮助。
现在,这可以通过单个 Route 53 * 通配符条目、为 *.example.com 配置的单个 CloudFront 分配以及一个或多个运行 HAProxy 的 EC2 实例轻松实现请求路径重写并将请求转发到 S3 存储桶。基本配置文件中的一行就可以完成请求重写:
http-request set-path /%[req.hdr(host)]%[path]
然后您需要代理将实际存储桶端点主机名发送到 S3,而不是浏览器提供的主机名:
http-request set-header Host example-bucket.s3.amazonaws.com
代理会将修改后的请求发送给 S3,将 S3 的响应返回给 CloudFront,CloudFront 会将响应返回给浏览器。
但是,如果您不想采用这种方法,因为需要服务器,那么替代解决方案如下所示:
为每个子域配置 CloudFront 分配,为分配设置 alternate domain name 以匹配特定子域。
将每个子域的分布的 Origin 配置为指向同一个存储桶,将 origin path 设置为 /one-specific-subdomain.example.com。 CloudFront 在将请求发送到 S3 之前将对 GET /images/funny-cat.jpg HTTP/1.1 的请求更改为 GET /one-specific-subdomain.example.com/images/funny-cat.jpg HTTP/1.1,从而导致您描述的行为。 (这与我为 HAProxy 描述的行为相同,但它是静态的,而不是动态的,因此每个子域一个分发;在这两种情况下,这都不是“重定向”——所以地址栏不会改变)。
在 Route 53 中为每个子域配置一个 A 记录别名,指向子域的特定 CloudFront 分配。
这一切都可以通过 API 以编程方式完成,使用任何一个 SDK,或使用 aws-cli,这是一种非常简单的测试、原型和脚本编写的方法,无需写很多代码。 CloudFront 和 Route 53 都完全支持自动化。
请注意,每个站点使用自己的 CloudFront 分配并没有明显的劣势,因为您的命中率不会有所不同,并且分配没有单独的费用——只有请求和带宽费用。
另请注意,CloudFront 有一个默认的 limit of 200 distributions per AWS account,但这是一个软限制,可以通过向 AWS 支持发送请求来增加。