はじめに
以前、SORACOM BeamでバイナリデータをAPIGateway経由でS3にアップロードするという記事を書いたのですが、今回はその記事の続編です。
別のアドカレでもLambdaの素晴らしさを少し語らせていただいたのですが(これ)、Lambdaはかなり便利だと思ってます!。私が今携わっている案件でも、常に十数台のLambdaが立ち上がって処理をしてくれています。
ある日の私
実際にその構成を使って画像を保存していたのですが、ある日
私「だいぶ溜まってきたしCLIでローカルにダウンロードしよっと」
aws s3 cp s3://bucketName/key ~/image
S3「Access deniedやで」
私「ファッ!?」
という一連の流れがあって、もしかしてこの構成間違ってる?ということに気がつきました。
なにがあった?
それまでの構成では、画像ファイルをバイナリのまま、APIGatewayにSORACOMBeamを通してRESTAPIでPOSTして、そのあとS3にPUTするようにしてました。
しかしそれでは、S3にPUTする際に必要なHeader情報が不足しているようでした。(それならそれでエラー吐いて欲しいものですが…)
果たして不足分のHeader情報を全て網羅できるのだろうか。いやできない。(反語)
※必要なHeader情報は公式ドキュメントを参照。
それじゃあどうする?
「便利なものは 使ってしまえ ホトトギス。」(字余り)
ということで、AWS-SDKでPUTすることにしました。SDKを利用すればHeader情報などをよしなに補ってくれますし、おすし。
そして、便利屋Lambdaさんの登場です。
APIGatewayから一度Lambdaにデータを渡して、LambdaからAWS-SDKを使ってPUTする。という流れです。
以前までの構成は前編を参照してください。
APIGatewayからLambdaを呼び出す
設定中に「APIGatewayにLambdaをinvokeする権限渡すけどええか?」と聞かれるのでOKしてあげてください。
マッピングテンプレートの設定
Content-TypeごとにどのようなテンプレートでLambdaに渡すかを設定します。
「Method Request passthrough」を選択しておけば問題ないです。
バイナリサポートの設定
バイナリデータを送信するときのContent-Typeを設定しておきます
Lambdaの作成
ランタイムはpython2.7です。
先ほどのマッピングテンプレートの形でeventに渡されてきます。
import json
import boto3
import base64
def lambda_handler(event, context):
print json.dumps(event)
try:
s3 = boto3.resource('s3')
bucket = s3.Bucket('bucketName')
# バイナリがBase64にエンコードされているので、ここでデコード
imageBody = base64.b64decode(event['body-json'])
# リクエストパスを組み合わせてKeyにする
imagePath = event['params']['path']
key = imagePath['key'] + '/' + imagePath['name']
print key
bucket.put_object(
Body = imageBody,
Key = key
)
print 'success!'
except Exception as e:
print 'Error!'
print e
これでLambda経由でS3に画像が保存されます。
SDKを利用してるので、Header情報やmetaデータはよしなにしてくれてます。
さいごに
やっぱりLambdaは便利ですね。
ではまた!