如何將CloudFront中的子網域對應到S3中的相同名稱?

如何將CloudFront中的子網域對應到S3中的相同名稱?

我一直在尋找一種方法來執行以下操作,如果有人能夠啟發我,我將不勝感激。

例如,在單一 CloudFront 實例中是否可以實作下列對應?

feature-a.domain.com => dev-bucket/feature-a
feature-b.domain.com => dev-bucket/feature-b
staging.domain.com   => dev-bucket/staging

等等..

用例是我希望能夠為每個 git 分支部署盡可能多的環境,該分支映射到 S3 上存在的儲存桶。這一切有可能嗎?

答案1

是的,這是可能的,但您需要使用 CloudFront 的 Lambda@Edge 增強功能,以便在將請求傳送到儲存桶之前操作請求參數。

我在中描述了一個可能的解決方案這個官方論壇貼文。下麵包含相同的解決方案。

Lambda@Edge 允許在 CloudFront 處理 HTTP 請求或回應時以程式設計方式存取它們,本質上是提供觸發掛鉤。 HTTP 事務以 JavaScript 物件的形式呈現,您可以觀察並修改該對象,然後將控制權傳回 CloudFront。

對於此應用程序,您需要在 CloudFront 配置中使用託管儲存桶端點的網站作為您的原始網域名稱(即不要從下拉清單中選擇儲存桶 - 使用適當的「s3-website」主機名稱輸入它) )並且您需要將Host標頭列入白名單以轉發到原點,即使我們實際上不會轉發它(我們將讀取它,然後與路徑一起操作它),並且即使通常將其轉發到S3 源無法按預期工作. ..但我們需要告訴CloudFront 將其列入白名單,以便可以讀取和操作它。

將下列 Lambda 函數配置為來源請求觸發器。此觸發器在檢查 CloudFront 快取並發生快取未命中之後、請求傳送到來源伺服器 (S3) 之前觸發。

'use strict';

// https://serverfault.com/a/930191/153161
// 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)

// set this to what we should remove from the incoming hostname, including the leading dot.

const remove_suffix = '.example.com';

// provide the correct origin hostname here so that we send the correct 
// Host header to the S3 website endpoint
// this is the same value as "origin domain name" in the cloudfront distribution configuration

const origin_hostname = 'example-bucket.s3-website-us-east-1.amazonaws.com';

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
  // we have to do this even if the above if() didn't match
  headers.host[0].value = origin_hostname;

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

還記得設定你的錯誤緩存最小 TTL 為 0以避免出現 CloudFront 快取錯誤回應。這是與快取行為設定中的最小/預設/最大 TTL 分開的設定。預設值為 5 分鐘,這是有道理的,但如果您沒有預料到這種行為,故障排除就會變得複雜。


請注意,Lambda@Edge 函數現在可以使用 v6.10 或v8.10Node.js 執行時期環境。上面的範例最初是為v6.10 編寫的,但與任一運行時相容,因為在v8.10 中處理程序有更多選項:它可以使用async/await,它可以直接傳回一個Promise,或者可以如上所示編寫使用回調介面。

相關內容