API Gateway + LambdaでS3にある画像を表示


概要

  • API GatewayとLambdaでS3にある画像を返却する
  • クライアント側からは単にURLにアクセスしたら画像が表示されるように見える
  • S3をpublicにすることなく画像を表示することができる (限定公開などが可能)
  • pythonでの実装

仕様がよく分からずハマったのでメモを残します.

やること

  1. Lambdaの作成
  2. API Gatewayの作成

S3は作成済みとします.

1. Lambdaの作成

Lambdaを適当な名前で作成します.ここではget_imageとしました.

また,ランタイムはPython 3.8を選択しました.

そして関数コードに以下のコードを登録します.

import boto3
import base64

def get_img_from_s3():
    s3 = boto3.client('s3')
    bucket_name = 'BUCKET_NAME'
    file_path = 'FILE_PATH'
    responce = s3.get_object(Bucket=bucket_name, Key=file_path)
    body = responce['Body'].read()
    body = base64.b64encode(body)
    return body


def lambda_handler(event, context):
    img = get_img_from_s3()
    return img

bucket_nameにS3のバケットの名前,file_nameに読み込みたいS3のオブジェクト(画像)のパスを渡しS3からオブジェクトを読み込みます.

その後読み込んだバイナリ形式のオブジェクトをbase64にエンコードして返却します.

LambdaにS3へのアクセス権限を付与

作成したLambdaはS3へのアクセス権限を持っておらず,このままだとアクセスが拒否されてしまうのでS3へのアクセス権限を付与します.

まず作成したLambdaのアクセス権限のページを開きます.

ここに自動で作成された実行ロールが割り当てられているので,この実行ロールのページを開きます.

ページ中央の青いポリシーをアタッチしますというボタンを押します.

このようにいろいろなポリシーが出てきます.

S3で検索するとS3に関するポリシーが出てきます.
今回はS3から画像を読み込むのでAmazonS3ReadOnlyAccessというポリシーをアタッチします.
これでLambdaからS3に保存されているファイルを読むことができるようになります.

以上でLambdaの設定は終了です.

2. API Gatewayの作成

続いてAPI Gatewayの作成をします.

APIタイプはREST APIを選択し,API名は適当にget_imageとしました.

続いてGETメソッドを追加し,統合タイプにはLambdaを,Lambda関数には先ほど作成したget_imageというLambda関数を指定しました.

これでAPI Gatewayが作成できたのでメソッドレスポンスの設定を行います.

まずレスポンスヘッダーにContent-Typeを追加し,レスポンス本文のコンテンツタイプにはimage/pngを追加しました.(今回はpngを読み込んだのでimage/pngにしました.)

次に統合レスポンスの設定を行います.

コンテンツの処理方法をデフォルトではパススルーになっていますが,バイナリに変換(必要な場合)を選択します.
またヘッダーのマッピングのマッピングの値を'*'とします.

以上でAPI Gatewayの設定も終了です.

最後にAPIのテストを行うと

このようにpngのバイナリを返すことができました!

実際にAPIをデプロイしてURLにアクセスすると画像が表示されます.

参考

Node.jsによる実装 Lambda + API Gateway入門。画像のDL