🐟

AWS Lambdaで画像版のWeb魚拓作成|Offers Tech Blog

2022/03/31に公開

あなたは誰?

こんにちは!Offers を運営している株式会社 overflow のバックエンドエンジニアの takkun7171 です。
いつの間にか 40 歳を超えてしまいましたが、Apex のソロダイヤを目指しつつ、エルデンリングやってます。
多分おじいちゃんになってもゲームやってますね。No Game, No Life です

これは何?

  • Web 魚拓というサービスがありますが、その画像版のような挙動を目標にします。すなわち元画像が存在する場合はそちらを表示しつつ、S3 にキャッシュ作成。元画像がない場合で S3 にキャッシュがある場合はキャッシュ表示。元画像が存在せず、キャッシュもない場合は 404 という感じの参考実装[1]を AWS Lambda で簡単かつ汎用的に実現してみました。
  • 悪意ある人に外部からたくさんアクセスされて、s3 に大量に画像が作成されないようにするため、簡単な認証をつけてあります。認証つけなくても参照はできるけど、保存は認証が必要という感じにしました

手順

以下コマンドで upload.zip を作ってください。ソースコードは見ればわかるので見てください。説明はしません w 上で書いてある通りです。なお zip はコマンドにある通り、lambda_function.rb vendor が対象です。clone したフォルダ自体を zip すると階層おかしくなって、Lambda が動かなくなります。これで地味にハマりました。。このあたりの aws の UI、めっちゃわかりにくいです。。

rbenv local 2.7.2
bundle install --path vendor/bundle
zip -r upload.zip lambda_function.rb vendor
  • upload.zip をうp
    zipファイルとして動作コードをアップロードしているスクリーンショット

  • 続いて環境変数の設定
    環境変数の編集画面のスクリーンショット

  • トリガーで API GATEWAY 追加します。レスポンスで画像返すので、バイナリーメディアタイプを*/*にしてください
    API設定画面のスクリーンショット

なんとこれで完了なので、テストする

  • rails コンソールなどで対象の画像 url を url エンコード
CGI.escape "https://upload.wikimedia.org/wikipedia/commons/c/c9/Moon.jpg"
  • 認証のための digest 作成
digest_head_key = "head_key_dayo"
data = "#{digest_head_key}:#{Time.now.utc.strftime("%Y%m%d")}"
digest_hex = Digest::SHA1.hexdigest(data)
  • エンドポイントにくくりつけてアクセス!(さっき作成した API Gateway のエンドポイントです)
{APIのエンドポイント}/default/fish_print_image?image_url=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fc%2Fc9%2FMoon.jpg&d={上の認証digest}
  • お月様の画像が表示されて、S3 に保存されてたら完了。やったね
    S3にオブジェクトが保存されていることが確認できるスクリーンショット
脚注
  1. 編集注: 他者の著作物を対象とする場合、複製した画像を一般に公開すると公衆送信権や送信可能化権を害する恐れがあるため用途にはくれぐれもご注意ください。 ↩︎

Offers Tech Blog

Discussion