JavaScript ⇄ AWS (API Gateway & Lambda) でデータやりとり

# はじめに
下の記事で、JavaScriptを使ってフォトシャワー表示をするフロントエンドを記述していました。
[フォルダ内の写真をフォトシャワーで表示してみる
](https://qiita.com/tomtom_pudding/items/be8b26dff40ece88d0b9)

今回は、AWS S3に保存されている写真を取得して表示をしてみたいと思います。つまりこんなイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989761/1d54ad9b-4f07-dc6d-1aa1-4a0e1cb7ad17.png)
JavaScriptの正式なロゴってこれであっているのだろうか...

# JavaScriptとAWS API Gatewayをつないで情報をLambdaへ送信
API Keyを用いたアクセスキー認証で行います。
LambdaとGatewayの連携、API Keyの取得方法に関しては以下の記事がとてもわかりやすいです。さすがはクラスメソッド様。。。
[ゼロから作りながら覚えるAPI Gateway環境構築
](https://dev.classmethod.jp/articles/getting-start-api-gateway/)

ajaxを用いてAPI GatewayにPOSTします。
下記では「changePicture」という関数を「modify_time」を引数にして作成しています。

```javascript
// APIでimage_listの中身を取得
function changePicture(modify_time){
    return $.ajax({
        url:'*****', // API Gateway Endpoint URL
        type:'POST',
        data:{body:modify_time}, // Lambdaに渡すデータ
        dataType:'json', // 応答のデータの種類 (xml/html/script/json/jsonp/text)
        contentType: "application/json;charset=UTF-",
        accessControlAllowOrigin: '*',
        headers:{
            'x-api-key': '*****' // API Gateway api key
        }
    })
}
```

この情報が、(api-key'****'に対応する)API Gatewayと紐づくLambdaに渡されます。

# JS(APIgw)から情報を受け取ったLambda関数の様相
渡された先のLambda関数の中身は以下のような感じになります。
このコードでは、<b>S3から画像情報を取得してJSに返す</b>ということをしています。

```python:lambda_function.py
def lambda_handler(event, context):
    #-- JSの「modifiy_time」の情報を取得
    last_modified_prev=int(event['body'][5:]) # 'body=1637330685' UNIX
    last_modified_prev=datetime.fromtimestamp(last_modified_prev) #UNIX to JST
    
    #-- boto3を立ち上げてobjectをget
    s3 = boto3.resource('s3')
    bucket = s3.Bucket(S3Bucket)
    print('scan start:',datetime.now())
    objs = bucket.meta.client.list_objects_v2(Bucket=bucket.name, Prefix=S3KeyPrefix)
    print('scan end:',datetime.now())
    
    #-- 画像情報を取得(filename, last modified)
    bodylist=get_image_info(objs,last_modified_prev)
    
    return {
        'statusCode': 200,
        'headers': {
          "Access-Control-Allow-Headers": "Content-Type",
          "Access-Control-Allow-Origin": '*',
          "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
        },
        "body": json.dumps(bodylist)
    }
```
S3から実際にデータを取得するメソッド(get_image_info)は割愛しています。

ポイントは(1)eventに入っている値と、(2)return値です。
(1)はJS上で書いたdata:{body:modify_time}に対応しています。実際event['body']の中身は'body=1637330685'となっており、数値はunixtimeを表しています(JSの時間変数はUNIX)。
(2)は、返却値を上記のようにすることで、実際にJS側でjsonデータ(bodylistの中身)を読み込むことが可能になります。bodylistの中身は例として下記の感じになっているとします。

```python
[
   {'filename':foo.jpg,'last_modified':some_unixtime1},
   {'filename':bar.jpg,'last_modified':some_unixtime2},
   ...,
]

```

# Lambdaの返却値をJavaScriptで読み込む

先に示した「changePicture」が、Lambdaの情報を無事に持って帰ってきてくれたかどうか？を判定し(done/fail)、
YES(done)ならimage_listというリストにforeach文でファイル名と時間の情報を追加しています。

```javascript
            // changePucture()で非同期通信をした結果をここで記載。
            changePicture(modify_time).done(function(data,textStatus,jqXHR) {
                console.log("成功:" + jqXHR.status);
                image_list = [];
                // 取得したファイル名を表示するimage_listに入れる
                $.each(data,(index,value) => {
                  image_list.push(value.filename);
                  modify_time = value.last_modified;
                });
            }).fail(function(jqXHR, textStatus, errorThrown) {
                console.log("ajax失敗:" + jqXHR.status);
                console.log(textStatus, errorThrown);
            });
```

このimage_listを使用して、親記事のようにフォトシャワーにしています。

# まとめ
1.API Gateway(to Lambda)への値の渡し方
2.Lambdaへの入力値の確認、returnの書き方
3.Lambdaからの返却値の読み出し方
をピックアップしてメモ程度に書き留めました。
これでJS x Lambdaのいろいろな応用ができそうです！