API Gateway + Lambdaでバイナリダウンロード

記事タイトルとURLをコピーする

こんにちは。技術3課の森です。
先日、ゴルフに行ったのですが、初めてみるグリーンに驚きを隠せませんでした。何が驚くかというとどこからみてもグリーンがうねってるんです。なので、パターで打ってもどこにいくかわからないので、とりあえず打つ戦法で切り抜けました。スコアは発表できません...。

はじめに

普通、API Gateway + Lambdaでバイナリダウンロードとかする場合、S3にバイナリを入れておき、そのURLをクライアントにレスポンスとして返して、クライアントがS3からダウンロードする感じだと思います。
① ユーザがURLを叩いて、API Gatewayにアクセス
② Lambdaを発火
③ Lambdaが処理して、S3のエンドポイントをレスポンスで返却
④ フォワードされて、S3からダウンロード

今回、やろうとしてることは、こんな条件です。
1. クライアント側でフォワードできない環境があった場合
2. ダウンロード対象のサイズが小さい場合
3. S3からLambdaへダウンロードして、そこからクライアントに返すと時間がかかるので、そこもカットしたい場合
のお話です。
どうすればいいのかということで、やったことは、Lambdaモジュールにダウンロード対象のオブジェクトを梱包するです。 構成はこちら。
① ユーザがURLを叩いて、API Gatewayにアクセス
② Lambdaが発火し、Lambdaモジュールと一緒に梱包されていたモジュールをダウンロード

それでは作っていきます。

構成

Lambda

以下は、Lambda FunctionをPythonで記述した例になります。

import base64

def main(event, context):
    response = {
        "statusCode": 200,
        "headers":{
            "Content-Type": "application/octet-stream",
        },
        "body": base64.b64encode(open('./binary_object', 'rb').read()).decode('utf-8'),
        "isBase64Encoded": True}
    return response


今回は、単純なダウンロードのみとしていますが、POSTでパラメータを渡して、条件分岐させて渡すバイナリオブジェクトを変えることも可能です。
この程度なら、ManagementConsoleに直接コードを書けますが、バイナリのオブジェクトを梱包したいので、virtualenvやServerlessFrameworkなどを使って作成してください。
環境の構築方法については、以前書いたブログ
【必見】AWS Lambdaをローカル環境で開発してみた
もしくは
【続】AWS Lambdaをローカル環境で開発してみた
をご確認ください。

梱包したファイル

今回の例で梱包したファイルを一覧化しました。

$ tree -L 1
.
├── bin/
├── binary_object
├── download.py
├── event.json
├── include/
├── lambda.json
├── lib/
├── pip-selfcheck.json
└── requirements.txt

3 directories, 6 files

API Gateway

次は、API Gatewayの設定です。

APIの作成

今回の例では、Lambdaプロキシ統合を使用しています。
後は、リージョンと先ほど作成したLambda Functionを指定して、「保存」をクリックしてください

バイナリサポート

次は、バイナリメディアタイプの設定を行います。
ここは、「∗/∗」とします。

APIのデプロイ

「リソース」の「アクション」の「APIのデプロイ」をクリックします。

「デプロイされるステージ」には「新しいステージ」、「ステージ名」は今回は「prod」としました。そして、「デプロイ」ボタンをクリックします。
すると、API Gatewayはデプロイされ、利用できる状態となります。

最後に、URLの確認です。
呼び出し用のURLを赤枠で囲っています。以上で完成です。

さいごに

ダウンロードしたモジュールと元々のモジュールが同一であることを確認するには、md5コマンドなどでハッシュ値が一致していることで確認できます。
今回は、さっと作っただけですので、本番で利用できる状態ではありません。
もう少し、構成を考えてアクセス数が増加した時のことは考えないといけませんね。
機会があれば、第二弾も検討します。