【问题标题】:How to get clean URLs on AWS Cloudfront (S3)?如何在 AWS Cloudfront (S3) 上获取干净的 URL?
【发布时间】:2017-08-02 04:23:07
【问题描述】:

我在 AWS S3 上托管我的静态网站,使用 Cloudfront 作为 CDN,我想知道如何才能使干净的 URL 正常工作。

我目前必须去example.com/about.html 获取关于页面。我更喜欢example.com/about 以及我的所有其他页面。另外,我不得不这样做,因为我的规范 URL 已经设置了元标记和搜索引擎,要更改它们会有点多。

Cloudfront 中是否有我看不到的设置?

更新

我探索了两种选择,下面是 Matt 详细介绍的一种。

首先是在上传到 S3 之前从文件中删除 .html,然后在该文件的 http 中编辑内容标题。这可能工作得很好,但我不知道如何从命令行编辑内容标题,我正在编写“推送网站更新”bash 脚本。

Second 由下面的 Matt 详细介绍,并利用 S3 识别根默认文件(通常是 index.html)的功能。可能是一个很好的方法,但它使我的本地测试具有挑战性,并且它在 URL 上留下了一个不适合我的斜杠。

【问题讨论】:

  • 我最终编写了一个构建脚本,该脚本复制了文件名末尾没有“.html”的所有 html 文件,然后将它们推送到 s3 存储桶,其中指定了 content-type html推送命令。

标签: amazon-web-services amazon-s3 amazon-cloudfront


【解决方案1】:

试试 AWS Lamda@Edge。它完全解决了这个问题。

首先,创建一个 AWS Lambda 函数,然后附加您的 CloudFront 作为触发器。

在此 AWS Lamda 页面的代码部分,将 sn-p 添加到下面的存储库中。

https://github.com/CloudUnder/lambda-edge-nice-urls/blob/master/lambdaRewrite.js

注意 repo 的自述文件部分中的选项

【讨论】:

    【解决方案2】:

    当您在 S3(以及通过扩展 CloudFront)中托管您的网站时,您可以将 S3 配置为在请求目录时加载“默认”文件。这称为“索引文档”。

    例如,您可以将 S3 配置为加载 index.html 作为默认文件。这样,如果请求是针对example.com/abc/,那么它将加载abc/index.html

    当你这样做时,如果他们请求example.com/abc/123.html,那么它将提供abc/123.html。因此默认文件仅在请求文件夹时适用。

    要解决您对example.com/about/ 的请求,您可以使用index.html 的默认文件配置您的存储桶,并将about/index.html 放入您的存储桶中。

    更多信息可以在亚马逊的文档中找到:Index Document Support

    【讨论】:

    • 很高兴知道:)
    • 嗨@Costa,如果这个或任何答案解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。
    • 这是一个有效的解决方法,但它有成本,比如重新排列我的整个工作目录。您的示例中还有一个斜杠,这不是我的规范 URL 当前在我的网站中列出的方式。知道这个选项存在绝对有帮助,谢谢!
    • 此外,我认为这种方法不能按预期工作,因为 Cloudfront 的默认根仅用于站点根,而不是子目录。授予:aws.amazon.com/blogs/compute/…
    • 我在有 S3 + Cloudfront 的网站上尝试过这个,但它不起作用
    【解决方案3】:

    当您的 S3 存储桶被配置为网站端点时,您可以通过使用自定义源来克服 丑陋的网址,并使用您的 Cloudfront 分发。缺点是您无法将 Cloudfront 配置为使用 HTTPS 在 Cloudfront 和您的源之间进行通信。您仍然可以使用 HTTPS,但不能使用端到端加密。

    https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-https-cloudfront-to-s3-origin.html

    【讨论】:

      【解决方案4】:

      您可以使用 Lambda 作为您网站的反向代理。

      在 API Gateway 中,您需要使用资源路径 =“{proxy+}”创建一个“代理资源”

      然后,创建一个 Lambda 函数来路由请求:

      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='/about'>link to about page</a>";
              return buildResponse(200, responseBody);
          }
      
          if (event.path == "/about") {
      
              var params = { 
                  Bucket: myBucket,
                  Key: 'path/to/about.html',
              };
      
              const data = await s3.getObject(params).promise();
      
              return buildResponse(200, data.Body.toString('utf-8'));
          }
      
          return buildResponse(404, 'Page Not Found');
      
      };
      
      
      function buildResponse(statusCode, responseBody) {
      
          var response = {
              "isBase64Encoded": false,
              "statusCode": statusCode,
              "headers": {
                  "Content-Type" : "text/html; charset=utf-8"
              },
              "body": responseBody,
          };
      
          return response;
      }
      

      然后您可以使用您的自定义域为您的 API 网关创建 CloudFront 分配。

      有关更多详细信息,请查看此答案: https://stackoverflow.com/a/57913763/2444386

      【讨论】:

      • 我最终编写了一个构建脚本,该脚本复制了文件名末尾没有“.html”的所有 html 文件,然后将它们推送到 s3 存储桶,其中指定了 content-type html推送命令。
      猜你喜欢
      • 2015-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-08
      • 1970-01-01
      • 2016-02-27
      相关资源
      最近更新 更多