【问题标题】:Can I use AWS API Gateway as a reverse proxy for a S3 website?我可以使用 AWS API Gateway 作为 S3 网站的反向代理吗?
【发布时间】:2020-01-05 23:00:24
【问题描述】:

我在 AWS S3 上有一个无服务器网站。但是 S3 有一个我想克服的限制:它不允许我拥有友好的 URL。

例如,我想替换 URL:

www.mywebsite.com/user.html?login=daniel

使用此 URL 友好:

www.mywebsite.com/user/daniel

所以,我想知道我是否可以将 Lambda 与 API Gateway 一起使用来实现这一点。

我的想法是:

API Gateway ---> Lambda 函数 ---> 获取 S3 资源

API 网关将获取任何请求,并将信息传递给 Lambda 函数,该函数将使用请求 URL 处理一些逻辑(可能包括一些数据库查询),然后从 S3 获取资源。

我知道 AWS API Gateway 的主要目的是成为 REST API 的网关,但我们也可以将它用作整个网站的代理吗?

【问题讨论】:

  • 您的 S3 资源是什么? SPA(Angular/React/Vue)还是其他?
  • SPA (AngularJS)

标签: amazon-web-services amazon-s3 aws-lambda aws-api-gateway serverless


【解决方案1】:

最好的选择是使用 CloudFront 作为反向代理,您可以使用 Viewer/Origin 响应请求来触发 lambda 并从 S3 获取资源。

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-examples.html

https://aws.amazon.com/blogs/networking-and-content-delivery/amazon-s3-amazon-cloudfront-a-match-made-in-the-cloud/

【讨论】:

  • Lambda@Edge 是否允许我做我在普通 Lambda 中可以做的所有事情?包括查询 DynamoDB 表?
  • 是的,它可以访问 DynamoDB 表,但 lambda@edge 中的函数会根据您的请求到达的区域触发,例如,如果您连接到美国的 CloudFront 边缘位置(假设 us-east-1)但是您的表在 us-west-2 中,us-east-1 中的 lambda 会触发 us-west-2 中的表,这可能会导致延迟等。(lambda@edge 函数会自动复制到所有区域)跨度>
  • 但为什么我们需要 CloudfFront + Lambda@Edge? Lambda 对 URL 重写还不够吗?为什么需要 CDN?
  • 一个简单的例子是编写原始请求/响应 lambda@function,然后使用 CDN 缓存来提供重定向响应,与每次 lambda 触发和成本的 APIGW 相比,这将减少 lambda 调用可以减少。
  • 所以,也许最好的办法是只缓存静态文件(图像、css、Javascript...),为它们创建一个单独的子域(static.mywebsite.com)。并且动态内容 (mywebsite.com) 将通过 API Gateway 直接访问,从而避免使用 CloudFront 和 Lambda@Edge 产生额外费用?
【解决方案2】:

可以将 API Gateway 用作 S3 网站的反向代理。

我可以按照以下步骤做到这一点:

  • 在 AWS API Gateway 中,使用资源路径 =“{proxy+}”创建“代理资源”
  • 转到 AWS Certificate Manager 并为您的网站 (*.mywebsite.com) 申请通配符证书
  • AWS 将告诉您在您的域注册商中创建 CNAME 记录,以验证您拥有该域
  • 验证您的证书后,转到 AWS API Gateway 并创建自定义域名(单击“自定义域名”,然后单击“创建自定义域名”)。在“域名”中输入您的域 (www.mywebsite.com) 并选择您刚刚创建的 ACM 证书(上面的第 1 步)。使用 path = "/" 创建一个“Base Path Mapping”,并在“destination”中选择您的 API 和阶段。
  • 之后,您需要添加另一个 CNAME 记录,其中包含为该自定义域名生成的 CloudFront“目标域名”。

在 Lambda 中,我们可以路由请求:

'use strict';

const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const myBucket = 'myBucket';

exports.handler = async (event) => {

    var responseBody = "";

    if (event.path=="/") {
        responseBody = "<h1>My Landing Page</h1>";
        responseBody += "<a href='/xpto'>link to another page</a>";
        return buildResponse(200, responseBody);
    }

    if (event.path=="/xpto") {
        responseBody = "<h1>Another Page</h1>";
        responseBody += "<a href='/'>home</a>";
        return buildResponse(200, responseBody);
    }

    if (event.path=="/my-s3-resource") {

        var params = { 
            Bucket: myBucket,
            Key: 'path/to/my-s3-resource.html',
        };

        const data = await s3.getObject(params).promise();

        return buildResponse(200, data.Body.toString('utf-8'));
    }

    return buildResponse(404, '404 Error');

};


function buildResponse(statusCode, responseBody) {

    var response = {
        "isBase64Encoded": false,
        "statusCode": statusCode,
        "headers": {
            "Content-Type" : "text/html; charset=utf-8"
        },
        "body": responseBody,
    };

    return response;
}

【讨论】:

    【解决方案3】:

    一个不错的选择是使用 CloudFront 和 Lambda@Edge。

    Lambda@Edge 允许您在 CloudFront CDN 网络的边缘位置运行 Lambda 函数。

    CloudFront 让您可以选择在其生命周期内挂钩各种事件并应用逻辑。

    这篇文章看起来可能与您正在谈论的内容相似。

    https://aws.amazon.com/blogs/networking-and-content-delivery/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/

    【讨论】:

    • Lambda@Edge 是否允许我做我在普通 Lambda 中可以做的所有事情?包括查询 DynamoDB 表?
    • 是的,你可以做所有这些事情。
    • 但为什么我们需要 CloudfFront + Lambda@Edge? Lambda 对 URL 重写还不够吗?为什么需要 CDN?
    • 另外,Lambda@Edge 的成本是 Lambda 的 3 倍。 Lambda 为每百万个请求 0.20 美元,而 Lambda@Edge 为每 100 万个请求 0.60 美元
    猜你喜欢
    • 2020-07-29
    • 2021-06-19
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 2021-04-11
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多