aws lambdaで画像版のweb魚拓作成

2 min read読了の目安(約2300字

これは何?

  • 例えばサイトの画像をクロールしたときに、画像にアクセスする期限がある場合、クロールできてもいずれアクセスできなくなります。このような場合、awsのs3などに保存してそちらを参照したいところです。このソリューションとしてawsのlambdaを選び、簡単かつ汎用的に実現してみました。
  • Web魚拓というサービスがありますが、その画像版のような挙動を目標にします。すなわち元画像が存在する場合はそちらを表示しつつ、s3にキャッシュ作成。画像がない場合でs3にキャッシュがある場合はキャッシュ表示。元画像が存在せず、キャッシュもない場合は404という感じです。ソースはこれ https://github.com/takundao71/lambda_fish_print_image/blob/master/lambda_function.rb
  • 悪意ある人に外部からたくさんアクセスされて、s3に大量に画像が作成されないようにするため、簡単な認証をつけてあります。認証つけなくても参照はできるけど、保存は認証が必要という感じにしました

手順

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

rbenv local 2.7.1(不要かも)
bundle install --path vendor/bundle
zip -r upload.zip lambda_function.rb vendor
  • upload.zipをうp
    Screenshot 2020-12-07 11.43.37.png

  • 続いて環境変数の設定
    Screenshot 2020-12-07 11.46.19.png

  • トリガーでAPI GATEWAY追加します。レスポンスで画像返すので、バイナリーメディアタイプを*/*にしてください
    Screenshot 2020-12-07 11.48.58.png

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

  • 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に保存されてたら完了。これで画像が消えても、このurlを参照すれば、表示され続けるということです、やったねw
    Screenshot 2020-12-07 11.51.48.png