簡體   English   中英

重定向到 S3 子文件夾的 index.html

[英]Redirect to index.html for S3 subfolder

我有一個域example.com 我有一個名為example.com的 S3 存儲桶設置,其中包含一個可用的index.html文件。 現在我想創建兩個名為oldnew的子文件夾,每個子文件夾包含一個單獨版本的單頁應用程序。 請求https://example.com/old (我喜歡在瀏覽器的地址欄中輸入請求時省略index.html )將打開old子文件夾中的index.html文件並請求https://example.com/new將打開index.html 執行這些重定向的最佳方法是什么? 我應該在 Route 53 example.com/old -> example.com/old/index.html中設置一些東西還是有更好的方法?

不需要 lambda 函數來增加項目的費用和復雜性。

以下答案引用自https://stevepapa.com/

https://stevepapa.com/my-great-new-post/預計將以與以下方式相同的方式工作: https://stevepapa.com/my-great-new-post/index.html

有一個聰明的小方法可以讓這些流向 Cloudfront 分發,它涉及更改 Cloudfront 默認顯示給您的來源。

選擇原始來源時,Cloudfront 將向您顯示 S3 存儲桶列表。 編輯原點

您無需從下拉列表中顯示的存儲桶中設置源,而是需要從其 S3 設置頁面中獲取該資源的靜態 Web 托管端點並手動將其彈出。 靜態托管端點 url 在哪里

對 Cloudfront 分發源使用靜態源意味着對該分發的任何請求都將使用 S3 的根對象查找,並且您的 404 響應應該隨着引用流過而消失。

重要的

這樣做之后:

否則,您所做的更改不會立即生效。

所以我昨晚也遇到了這個問題。

問題如下:當配置為網站存儲桶時,S3 是寬容的並且具有索引文檔設置,設置為index.html並且這在根目錄中應用,即example.com實際上被重定向到example.com/index.html ,它也會在子文件夾級別應用,因此example.com/newexample.com/new/都應該重定向到example.com/new/index.html ,存儲桶中會有一個對象。 (否則,您會收到NoSuchKey錯誤。)

然而,您隨后將自己“升級”到 CloudFront,可能是為了 HTTPS,並且此功能消失了。 CloudFront 改為對 S3 進行顯式 API 調用,因此不會觸發索引文檔讓步。 它確實適用於根目錄,但不適用於子文件夾。

RoutingRules解決方案在我看來並不干凈,因為通過指定KeyPrefixEquals而不是 key exactly equals(不存在)我認為你會得到意想不到的匹配。

相反,我實施了一個 Lambda@Edge 規則,該規則重寫 CloudFront 向 S3 發出的請求以在其中具有適當的鍵值。

從此處的 Lambda 文檔和 A/B 測試示例開始: https ://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-examples.html#lambda-examples-general-examples

將代碼更改為:

'use strict';

exports.handler = (event, context, callback) => {
    /*
     * Expand S3 request to have index.html if it ends in /
     */
    const request = event.Records[0].cf.request;
    if ((request.uri !== "/") /* Not the root object, which redirects properly */
        && (request.uri.endsWith("/") /* Folder with slash */
            || (request.uri.lastIndexOf(".") < request.uri.lastIndexOf("/")) /* Most likely a folder, it has no extension (heuristic) */
            )) {
        if (request.uri.endsWith("/"))
            request.uri = request.uri.concat("index.html");
        else
            request.uri = request.uri.concat("/index.html");
    }
    callback(null, request);
};

並將其發布到您的 CloudFront 發行版。

使用 HTML 重定向文件可以更簡單地完成此操作

  1. 創建一個名為 my-great-new-post 的普通文件(不用擔心不會與同一存儲桶中的文件夾發生名稱沖突)

  2. 在那個文件中寫一個元重定向代碼(我粘貼了下面的代碼)

  3. 將文件上傳到根存儲桶(my-great-new-post 文件夾所在的位置)

  4. 修改新文件的元數據並制作 Content-Type:text/html

這是文件的內容:

 <;DOCTYPE html> <html> <head> <meta http-equiv="refresh" content="0. url=/my-great-new-post/index.html"> </head> <body> </body> </html>

如果您使用的是 CloudFront,則可以使用CloudFront 函數來創建簡單的重定向。

我修改了@jkingok 的解決方案。

  1. 轉到 CloudFront,然后單擊 Functions。
  2. 單擊創建函數,輸入名稱和可選描述
  3. 在開發部分,輸入下面的代碼片段並從發布選項卡發布。
    function handler(event) {
      var request = event.request;
      if (request.uri !== "/" && (request.uri.endsWith("/") || request.uri.lastIndexOf(".") < request.uri.lastIndexOf("/"))) {
      if (request.uri.endsWith("/")) {
         request.uri = request.uri.concat("index.html");
      } else {
         request.uri = request.uri.concat("/index.html");
      }
     }
      return request;
   }

函數完成后,您可以通過轉到分配的“行為”選項卡來使用該函數,選擇要修改的路徑模式,然后在“函數關聯”下,對於查看器請求,選擇“CloudFront 函數”作為函數類型,然后在下拉列表中選擇您創建的函數。

函數關聯截圖

保存行為后,您可以測試您的網站。

注意:此解決方案將不帶擴展名的每個 URL 重定向到“URL/index.html”,您可以將函數的行為修改為適合您的方式。

當您使用 S3 啟用和配置靜態托管時,您需要通過存儲桶網站端點訪問該站點。 您可以在靜態網站托管部分的存儲桶屬性中找到此 URL。

S3 靜態網站托管設置

網站端點的 URL 將如下所示:

http://example-bucket.s3-website-eu-west-1.amazonaws.com/example-folder/

然而(令人困惑的)存儲在 S3 中的對象也可以通過不同的 URL 訪問,這個 URL 不遵守子文件夾的索引規則。 這個 URL 看起來像這樣:

https://example-bucket.s3-eu-west-1.amazonaws.com/example-folder/
  1. 配置您的 Bucket 以提供靜態網站
  2. 創建CloudFront 分配:將您的存儲桶設置為Origin並將OriginPath留空(默認值: /
  3. 創建鏈接到您的CloudFront 分配Route53 RecordSet

您可以在此處找到有用的演練

問題:如果您的客戶輸入example.com (沒有old / new )會發生什么?

編輯: 2.是可選的。 您還可以將您的 Route53 RecordSet 鏈接到您的靜態網站,但CloudFront 使您能夠使用https (借助AWS Certificate Manager )為您的網站提供服務。

如果您使用 CDK 創建帶有 S3 源的 CloudFrontWebDistribution,那么您的第一個猜測可能是這樣做:

                OriginConfigs = new[] {
                    new SourceConfiguration {
                        S3OriginSource = new S3OriginConfig
                        {
                            S3BucketSource = bucket
                        }
                        Behaviors = new[] { new Behavior { IsDefaultBehavior = true } }
                    }
                }

但是,要將 cloudfront 配置為使用 website-bucket-url(確實具有將目錄解析為 index.html 的行為),您需要使用:

                OriginConfigs = new[] {
                    new SourceConfiguration {
                        CustomOriginSource = new CustomOriginConfig
                        {
                            DomainName = bucket.BucketWebsiteDomainName,
                            OriginProtocolPolicy = OriginProtocolPolicy.HTTP_ONLY
                        },
                        Behaviors = new[] { new Behavior { IsDefaultBehavior = true } }
                    }
                }

您需要將協議指定為 HTTP_ONLY,因為網站存儲桶不支持 HTTPS。 CustomOriginSource 的默認值為 HTTPS_ONLY。

您可以嘗試設置重定向規則,這是一個未經測試的規則。

<RoutingRules>
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals>old</KeyPrefixEquals>
    </Condition>
    <Redirect>
      <ReplaceKeyWith>old/index.html</ReplaceKeyWith>
    </Redirect>
  </RoutingRule>
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals>new</KeyPrefixEquals>
    </Condition>
    <Redirect>
      <ReplaceKeyWith>new/index.html</ReplaceKeyWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM