Host Wildcard Subdomain in One S3 Bucket(with Lambda@Edge)

blackbing Playground
5 min readApr 21, 2021

--

用一個 S3 bucket 來 Host 多個子網域內容(with Lambda@Edge)

我希望在每個 pr build 都能自動建立一個環境來做測試。這樣我不需要為了要 code review 而要在 local 切換 branch,減少 switch 的成本。因此我又把腦筋動到 lambda@Edge 了,不需要維護機器就是爽。

PR build

我希望在每個 pr build 都能自動建立一個環境來做測試。這樣我不需要為了要 code review 而要在 local 切換 branch,減少 switch 的成本。

像這樣: https://acd1e93deh8h.example.link 每個 pr 都可以自動產生一個可以執行的環境來測試,簡化測試與加速迭代。

但要將 wildcard subdomain 指到 s3 我還真沒做過,不太確定是否可以這樣玩。稍微找了一下有人寫 github 的 Action(pr-automation-with-s3),翻了一下他的做法原來是在每個 pr 都直接 create 一個新的 bucket,pr 關掉再把 bucket 刪掉。

不過這樣權限會開太大,而且單純 http 不夠,還是得接 cloudfront 才有 https,不然一個不支援跨域,不支援 FB 登入,要做整合測試真的很煩人。

lambda@Edge

因此我又把腦筋動到 lambda@Edge 了,不需要維護機器就是爽,理論上只要可以將 wildcard 的路由指到 cloudfront 就可以交給 lambda@Edge 做了。嘴巴說說很簡單,但實際上要注意的點還不少,因此我也紀錄一下怕我的金魚腦忘記。

事前準備:

部署 s3 靜態網頁到 CloudFront。

相關的文章可以參考,這邊不贅述:
1. 使用 AWS S3, Cloudfront 部屬 Custom Domain HTTPS 靜態網頁
2. How do I use CloudFront to serve a static website hosted on Amazon S3

Wildcard SSL certificate

這個不在本文的範圍,不過你需要先準備好,可以參考:ACM certificate characteristics

S3bucket Object

由於這個 bucket 要 serve 多個子網域的內容,因此將每個 folder 都當成是一個網域的內容,最外面的 index.html 作為 404 的內容。

s3 bucket object for multiple subdomain

正文開始

首先要將 CloudFront 的 CNAMEs 指到 wildcard 的 domain。這樣就可以將這個 domain 的所有 request 都指定到這個 distribution。

wildcard domain distribution setting

這個步驟做完之後就會讓所有的 domain 都會回應 root 的 index.html,例如:

但我們希望它要回應 folder 裡頭的 index.html。這就得動一些手腳了。

lambda@Edge 登場

Viewer Request

首先我們需要將 subdomain 傳給 origin request,這個 function 拿到之後建立一個 X-Domain-Hash header 往後丟。

Origin Request

然後再根據 x-domain-hash 來決定要轉到哪一個 uri。

Origin Response

最後處理 SPA 的 404。這邊要自己處理的細節是 SPA 需要將所有的 request 都導到 index 來處理。

大功告成

如此一來就可以將所有的 subdomain 內容丟到同一個 bucket 來 host 了。可喜可賀。🎉🎉🎉

後來想想這個應用其實可以蠻廣的,除了我一開始要做 pr build 的目的之外,如果你的網站或者靜態資源需要根據不同 subdomain 來 serve,就可以這樣子應用,在同一個 bucket 的好處就自己評估了,像是可以依照一些規則來處理 expire 等等。

--

--

blackbing Playground

Bingo Yang。記錄一些生活與工作的雜事,偶爾會寫一些前端網頁開發的心得,過去的足跡在 http://blog.blackbing.net