透過 s3 + api gateway + lambda 實作 image resize

首先要先新增一個 s3 bucket, 這邊不多說明如何建置 s3 bucket, 但是要記得 bucket 須為 public
s3 這邊要注意以下幾點
- 記得 bucket 要為 public
- bucket 要啟用 static website hosting
- 切換到 properties

4. 拉到最下面應該會看到 static website hosting, 請點選 Edit

5. 將 static website hosting enable, 且設定 hosting type 為 host a static website

6. 設定 redirection rules
[
{
"Condition": {
"HttpErrorCodeReturnedEquals": "404",
"KeyPrefixEquals": ""
},
"Redirect": {
"HostName": "<api gateway hostname>",
"HttpRedirectCode": "307",
"Protocol": "https",
"ReplaceKeyPrefixWith": "test/resize?key="
}
}
]
備註:
"ReplaceKeyPrefixWith": "<api gateway path>?key="這邊的 key 不能替換掉, 因為 lambda 會抓這邊的 key 去解析
這邊 rule 的意思是倘若存取到這個 bucket 的話, 都會跳轉到 <api gateway hostname>/<api gateway path>?key=<s3 filename>, 緊接著會觸發 lambda 去 resize image
建置 Lambda
- 新增 lambda function

2. Function name 輸入 resize, 且選擇合適的 nodejs 版本以及架構, 所選的架構要記一下, 因為稍後再安裝 nodejs 套件的時候需要指定, 且新增一個 aws role


3. 新增完後點擊“下載” nodejs lambda 壓縮檔案
建議先砍掉 node_modules, 然後重新執行 npm install,
但要注意 sharp 檔案需看先前新增 lambda 時是使用什麽架構, 倘若是使用 x86_64, 則使用以下指令 npm install --arch=x64 --platform=linux sharp@0.23.2,
然後因為 lambda 的 function 還會用到 aws-sdk, 因此 npm 也要安裝 aws-sdk
4. 新增完後會在列表看到剛剛新增的 lambda

5. 接著將剛剛下載下來的 zip 檔案上傳到 lambda, 點選Upload From 接著選取.zip file, 最後選擇剛剛下載下來的 zip file
ps: 因為檔案稍大因此可能會上傳一小段時間

6. 去到 iam 尋找上面所新增的 role, 找到後點選剛剛新增的 role, 我們這邊要賦予該 role 擁有存取 aws s3 的權限, 因為在 image 在 resize 後會將 resize 的圖片上傳到 s3, 而我們這邊給予該 role aws s3 full access

7. 選取 attach policies 後搜尋 AmazonS3FullAccess

8. 編輯環境變量, 點選 Configuration 後接著點選 Environment variables

9. 因為 lambda 有用到 BUCKET, 以及 URL env 因此要新增這兩個出來
BUCKET: s3 bucket name
URL: s3 static website hosting endpoint url

建置 API gateway
- 點選 Create API

2. 我們這邊選取 REST API 且點選 Build

3. 輸入 api 名稱, 輸入完後點選新增

4. 新增 resource , 我們可以把 resource 想成是路徑!!
點選 Action 後選擇 Create Resource

5. 輸入 resource name, resource name 預設會成為路徑
例如: resource name 輸入 helloworld
那麼 resource path 會是 /helloworld

6. 新增完 resource 後, 我們緊接著要新增 restful method
a. 選擇 Lambda Function
b. 選擇 Lambda 的 region
c. 選擇 or 輸入上面所新增的 Lambda function name
d. 勾選 Use Lambda Proxy integration

7. deploy api (產生的 api hostname 以及相對應的 path 以及 method)
a. 點選 deploy api

b. 因為一開始沒有新增過 stage, 因此選擇 create stage

c. 新增完後可以去 stage 查看剛剛新增的資訊以及 api
應該會看到類似以下的畫面, 倘若想要查看 api host 可以點選 GET 或者其他的 method 查看

測試 resize image
使用 s3 新增的 static website hosting 的 Bucket website endpoint,
假如 endpoint 為 http://test.bucket.s3, 則可以在網址列輸入
http://test.bucket.s3/100x100/<filename>
這樣的話會在 s3 新增一個 100x100 的 folder, 而裡面會有 filename 即代表成功實作 resize image lambda
參考資料:
- https://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html
- https://aws.amazon.com/tw/blogs/compute/resize-images-on-the-fly-with-amazon-s3-aws-lambda-and-amazon-api-gateway/
- https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html
- https://docs.aws.amazon.com/AmazonS3/latest/userguide/EnableWebsiteHosting.html
- https://docs.aws.amazon.com/zh_tw/AmazonS3/latest/userguide/how-to-page-redirect.html
- https://stackoverflow.com/questions/64598842/aws-s3-redirection-rules-not-letting-me-saving-it
- https://sharp.pixelplumbing.com/install
- https://leesonhsu.blogspot.com/2018/03/awss3-imageresize.html