从 AWS 中的通配符域提供大量静态站点

Serving a multitude of static sites from a wildcard domain in AWS

我这里有一个非常具体的问题,我们有一个我们已经拥有并维护的系统,该系统涉及使用子域将人们路由到特定的应用程序。

在传统服务器上运行如下;我们有一个通配符子域 *.domain.com 路由到 nginx 并提供一个文件夹

so myapp.domain.com > nginx > 提供 myapp 应用程序文件夹 > myapp 文件夹包含一个静态站点

我正在尝试以某种方式将其迁移到 AWS,我基本上需要在 AWS 中做类似的事情,我考虑过将每个静态应用程序放入 s3 存储桶然后将通配符域放入路由中的想法53,但我不确定 s3 如何知道要提供哪个文件夹,因为该功能不是 route 53 的一部分

有人有什么建议吗?

感谢您的帮助

  1. 创建 Cloudfront 分配

  2. 添加云端分布中的所有Alternate CNAMEs记录

  3. 添加自定义源作为 EC2 服务器。

  4. 根据您的要求设置行为。

  5. 在服务器中配置 nginx 虚拟主机以路由到特定文件夹。

CloudFront + Lambda@Edge + S3 可以做到这一点 "serverless."

Lambda@Edge 是一项 CloudFront 增强功能,允许将请求和响应的属性表示和操作为简单的 JavaScript objects。触发器可以设置为在请求处理期间触发,在检查缓存之前("viewer request" 触发器)或在请求进入 back-end("origin server",一个 S3 网站托管端点之前,在这种情况下)在缓存未命中("origin request" 触发器)之后...或在响应处理期间,在从源接收到响应之后但在考虑将其存储在 CloudFront 缓存中之前("origin response" 触发器),或者在完成对浏览器的响应时("viewer response" 触发器)。响应触发器还可以检查原始请求 object.

以下代码段是我最初在 AWS 论坛 posted 发表的内容。它是一个 Origin Request 触发器,它将原始主机名与您的模式进行比较(例如,域必须匹配 *.example.com),如果匹配,则主机名前缀 subdomain-here.example.com 是从为子域命名的文件夹中提供请求的.

lol.example.com/cat.jpg        -> my-bucket/lol/cat.jpg
funny-pics.example.com/cat.jpg -> my-bucket/funny-pics/cat.jpg

通过这种方式,您可以从一个存储桶中提供任意多个子域的静态内容。

为了访问原始传入 Host header,需要将 CloudFront 配置为 whitelist the Host header for forwarding to the origin,即使 Lambda 函数执行的最终结果将是修改该值在原始人真正看到它之前。

代码其实很简单 -- 以下大部分是解释性注释。

'use strict';

// if the end of incoming Host header matches this string, 
// strip this part and prepend the remaining characters onto the request path,
// along with a new leading slash (otherwise, the request will be handled
// with an unmodified path, at the root of the bucket)

const remove_suffix = '.example.com';

// provide the correct origin hostname here so that we send the correct 
// Host header to the S3 website endpoint

const origin_hostname = 'example-bucket.s3-website.us-east-2.amazonaws.com'; // see comments, below

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const host_header = headers.host[0].value;

    if(host_header.endsWith(remove_suffix))
    {
        // prepend '/' + the subdomain onto the existing request path ("uri")
        request.uri = '/' + host_header.substring(0,host_header.length - remove_suffix.length) + request.uri;
    }

    // fix the host header so that S3 understands the request
    headers.host[0].value = origin_hostname;

    // return control to CloudFront with the modified request
    return callback(null,request);
};

请注意,来自 S3 的索引文档和重定向可能还需要源响应触发器以根据原始请求规范化 Location header。这将完全取决于您使用的 S3 网站功能。但以上是一个说明总体思路的工作示例。

请注意,const origin_hostname 需要设置为在 CloudFront 源设置中配置的存储桶端点主机名。在此示例中,存储桶位于 us-east-2 且网站托管功能处于活动状态。