从 AWS 中的通配符域为大量静态站点提供服务 [英] Serving a multitude of static sites from a wildcard domain in AWS

查看:23
本文介绍了从 AWS 中的通配符域为大量静态站点提供服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've got a pretty specific problem here, we've got a system that we already have and maintain, the system involves using subdomains to route people to specific apps.

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

on a traditional server that goes like follows; we have a wildcard subdomain, *.domain.com that routes to nginx and serves up a folder

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

so myapp.domain.com > nginx > serves up myapp app folder > myapp folder contains a static site

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

I'm trying to migrate this in some way to AWS, I basically need to do a similar thing in AWS, I toyed with the idea of putting each static app into an s3 bucket and then the wildcard domain in route 53 but i'm unsure how s3 would know which folder to serve up as that functionality isn't part of route 53

大家有什么建议吗?

感谢您的帮助

推荐答案

CloudFront + Lambda@Edge + S3 可以无服务器"做到这一点.

CloudFront + Lambda@Edge + S3 can do this "serverless."

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

Lambda@Edge is a CloudFront enhancement that allows attributes of requests and responses to be represented and manipulated as simple JavaScript objects. Triggers can be provisioned to fire during request processing, either before the cache is checked ("viewer request" trigger) or before the request proceeds to the back-end ("origin server", an S3 web site hosting endpoint, in this case) following a cache miss ("origin request" trigger)... or during response processing, after the response is received from the origin but before it is considered for storing in the CloudFront cache ("origin response" trigger), or when finalizing the response to the browser ("viewer response" trigger). Response triggers can also examine the original request object.

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

The following snippet is something I originally posted at the AWS Forums. It is an Origin Request trigger which compares the original hostname to your pattern (e.g. the domain must match *.example.com) and if it does, the hostname prefix subdomain-here.example.com is request is served from a folder named for the subdomain.

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

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

In this way, static content from as many subdomains as you like can all be served from a single bucket.

为了访问原始传入的 Host 标头,需要将 CloudFront 配置为 将 Host 标头列入白名单以转发到源,即使 Lambda 函数执行的最终结果是在源真正看到它之前修改该值.

In order to access the original incoming Host header, CloudFront needs to be configured to whitelist the Host header for forwarding to the origin even though the net result of the Lambda function's execution will be to modify that value before the origin acually sees it.

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

The code is actually very simple -- most of the following is explanatory comments.

'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 的索引文档和重定向可能还需要一个 Origin Response 触发器来根据原始请求规范化 Location 标头.这将取决于您使用的 S3 网站功能.但以上是一个说明总体思路的工作示例.

Note that index documents and redirects from S3 may also require an Origin Response trigger to normalize the Location header against the original request. This will depend on exactly which S3 website features you use. But the above is a working example that illustrates the general idea.

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

Note that const origin_hostname needs to be set to the bucket's endpoint hostname as configured in the CloudFront origin settings. In this example, the bucket is in us-east-2 with the web site hosting feature active.

这篇关于从 AWS 中的通配符域为大量静态站点提供服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆