API Gateway + CognitoでWebサイトからバックエンドの処理を呼び出す

# やりたいこと
前回の記事（ https://qiita.com/mkttks/items/c30e993adb520869dbb4 ）ではAWS Lambda と Amazon DynamoDB を使用してバックエンドの処理を実装しました。
今回はAPI Gatewayを使ってWebサイトからこのバックエンドの処理を使えるようにします。

内容は引き続き下記の公式チュートリアルに沿ったものです。（※ただしチュートリアル通りに進めると権限まわりの設定で詰まります。）
https://aws.amazon.com/jp/getting-started/hands-on/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito/

# システム構成図
![api gatewayのシステム構成図](https://d1.awsstatic.com/Test%20Images/Kate%20Test%20Images/Serverless_Web_App_LP_assets_05.d1ecdfaab160d7dc00ddbc9e0245fa34b8d8f26b.png)
公式チュートリアルから引っ張ってきた図だとこんな感じです。API GatewayがWebサイトとLambdaを繋ぐイメージですね。

# 手順

## 新しいAPIを作成する
まず新しいAPIを作成します。
APIをすごく雑に説明するとWebサイトがバックエンドの処理を呼び出すための呪文集みたいなものです。API Gatewayを使うとこのAPIを作ることができます。

### API Gatewayにアクセス
1. AWS Console( https://console.aws.amazon.com/ )にサインインして検索欄に「api」と入力
1. 出てきたAPI Gatewayのアイコンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/cd0bc741-79a1-1d32-6e9d-1f209de21b84.png)

### 新しいAPIを作成
1. 左のメニューの「API」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/a125235d-cfed-dbc9-febd-4d36c8f63114.png)
1. 「APIタイプを選択」->「REST API」の「構築」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/7b94eef0-44bc-cc44-b977-c4fe0c839fc1.png)
1. 「新しいAPIの作成」で「新しいAPI」にチェックを入れる
1. 「名前と説明」->「API名」で任意の名前を入力（ここではWildRydesとします）
1. 「エンドポイントタイプ」で「エッジ最適化」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/c602b48f-e49b-0d27-a61e-87e546763353.png)
1. 「APIの作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/2f424c74-d177-3c98-70f8-9fd25d59bf40.png)

新しいAPIができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/6f7670f7-8db9-a444-d988-74ce88594321.png)

## 新しいリソースとメソッドを作成する
前の手順で作ったAPIにリソースとメソッドを追加します。

### リソースを作成
1. 「API」->「（API名）」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/0e8f0244-5f9e-d049-452d-0799d44b3ab2.png)
1. 左のメニューの「リソース」を選択
1. 「アクション」ドロップダウンから「リソースの作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/b81a0990-7ad6-165d-04f7-353ecd8680b2.png)
1. 「リソース名」に任意の名前を入力（ここではrideとします）
1. 「リソースパス」は自動入力されるのでそのまま
1. 「API Gateway CORS を有効にする」にチェックを入れる
1. 「リソースの作成」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/30241b08-0746-1803-9d7a-e5259ffe2e3e.png)

「/ride」というリソースが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/1823ce30-10c1-7509-5afc-cf8528b85dfb.png)

### メソッドを作成
1. 「/ride」リソースが選択された状態で「アクション」ドロップダウンから「メソッドの作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/27fec9ae-6472-e857-5ffd-f31425fd4403.png)
1. 表示されるドロップダウンから「POST」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/97334f8f-2ffc-ed7b-79c0-10887bad2415.png)
1. ドロップダウンの右のチェックマークをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/c2f07616-1215-3992-dfff-29a0e6eed8c6.png)
1. 「統合タイプ」で「Lambda関数」にチェックを入れる
1. 「Lambdaプロキシ統合の使用」にチェックを入れる
1. 「Lambdaリージョン」に前回作成したLambda関数が置かれているリージョンを選択する（ここではap-northeast-1）
1. 「Lambda関数」に前回作成したLambda関数の関数名を入力（ここではRequestUnicorn）
1. 「保存」ボタンをクリック
1. 「Lambda 関数に権限を追加する」というダイアログが表示された場合は「OK」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/a381a393-4286-f705-3c68-f772a978c96f.png)

メソッドが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/55df7aa4-5c1b-1711-16ee-dcf51d135a50.png)

## アクセス許可を設定する
続いてアクセス許可の設定をします。今回はWebサイトにログインしたユーザのみがAPIを使えるように設定します。

### Lambda関数のIAMロールにアクセス許可を付与
Lambda関数とAWS Cognitoが連携できるように、Lambda関数に設定しているIAMロールにCognitoへのアクセス許可を付与します。
1. 「API」->「（API名）」->「リソース」->「/ride」->「POST」を選択
1. 右側の「Lambda （Lambda関数名）」のリンクをクリック（別タブでLambda関数の設定画面が開きます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/f2fa3901-81fb-9b73-5bd3-9398d678df0e.png)
1. 「設定」タブの「アクセス権限」->「実行ロール」->「ロール名」のリンクをクリック（別タブでIAMロールの設定画面が開きます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/0fb90481-aebe-640a-7b29-a8cee5999c96.png)
1. 「許可」->「許可ポリシー」->「許可を追加」をクリック
1. 「ポリシーをアタッチ」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/956a7a4f-dd19-c238-3905-36e59614aa69.png)
1. 検索欄に「cognito」と入力
1. 出てきた「AmazonCognitoPowerUser」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/c806befd-da77-ef66-56fc-4cec60efdee3.png)
1. 「許可を追加」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/1b767dd6-2303-f932-0470-9316d8199134.png)

### オーソライザーを作成
続いてオーソライザーを作成します。これはAPI GatewayをCognitoと連携させるために必要な設定です。
1. API Gatewayの「API」->「（API名）」を選択
1. 左のメニューの「オーソライザー」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/03c9e524-5379-2afb-2a86-62e5f15c4ed7.png)
1. 「新しいオーソライザーの作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/b7f9b40b-70a8-f388-7398-85f425e95b29.png)
1. 「オーソライザーの作成」->「名前」に任意の名前を入力（ここではwildrydes-cognito-authorizerとします）
1. 「タイプ」で「Cognito」にチェックを入れる
1. 「Cognitoユーザープール」で前々回作成したCognitoを指定（ここではWildRydes）
1. 「トークンのソース」にAuthorizationと入力
1. 「作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/86af6179-1943-984a-3d09-089cd661a613.png)
1. 左のメニューの「リソース」を選択
1. 「/ride」のPOSTをクリック
1. 「メソッドリクエスト」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/c9d86726-9c24-f460-e5c0-d588d35103e6.png)
1. 「設定」->「許可」で「Cognitoユーザープールオーソライザー」の下の先ほど作ったオーソライザーを選択
1. ドロップダウンの右側のチェックボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/36412959-5e54-6dfc-0496-209cc5487d8c.png)

これでアクセス許可の設定ができました。

## APIをデプロイする
設定が完了したのでAPIをデプロイしましょう。

### APIをデプロイ
1. 「アクション」ドロップダウンから「APIのデプロイ」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/39141987-165c-da59-81ea-426785f75616.png)
1. 「APIのデプロイ」ダイアログ->「デプロイされるステージ」で「[新しいステージ]」を選択
1. 「ステージ名」に任意の名前を入力（ここではprodとします）
1. 「デプロイ」ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/dfba4526-ae47-d741-486e-0adf2fff7259.png)

APIがデプロイされました。「URLの呼び出し:」の右側のURLを次の手順で使うためコピーしておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/da740fd1-128e-8aae-14fc-4c1de65d819f.png)

## Webサイト構成を更新する
それではWebサイトの方でAPIを呼び出す実装をしましょう。ソースコードは前々回作成したものを利用します。
あらためてサンプルコードを取得した方はこちらからどうぞ
```aws s3 cp s3://wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website ./ --recursive```

### AWS Cloud9にアクセス
1. AWS Consoleの検索欄で「cloud9」と入力
1. Cloud9のアイコンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/a9a4cec0-7ac3-a929-027a-f1460a71e200.png)
1. 前々回作成した環境の「Cloud9 IDE」を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/4b69f6e6-9bf5-18bd-68cd-159ddc831bfc.png)

### ソースコードを編集
1. wildryde-site/js/config.jsを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/63f9d046-05ba-fc55-ee5b-3cee94fbb57f.png)
1. apiテーブルのinvokeUrlに先ほど作ったAPIの「URLの呼び出し:」の右側のURLを張り付け
```
window._config = {
    cognito: {
        userPoolId: '｛ユーザープールID｝', // e.g. us-east-2_uXboG5pAb
        userPoolClientId: '｛ユーザープールクライアントID｝', // e.g. 25ddkmj4v6hfsfvruhpfi7n4hv
        region: '｛リージョン名｝' // e.g. us-east-2
    },
    api: {
        invokeUrl: '（作ったAPIのURL）' // e.g. https://rc7nyt4tql.execute-api.us-west-2.amazonaws.com/prod',
    }
};
```
### ソースコードを編集２（サンプルのアップデート）
公式が出しているサンプルコードの内容が一部古くなっており、手動で変えないといけない箇所があるそうなので追記します。

1. 「wildryde-site/ride.html」を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/d17b6867-a37c-4d2b-cbb3-a4df9dfe4fe7.png)
1. Ctrl + Fを押して検索欄に「arcgis」と入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/c0ccf031-7fe3-3534-ec8a-140a6033c404.png)
1. 該当する行2か所を以下のように修正
```
<script src="https://js.arcgis.com/4.6/"></script>
```
```
 <link rel="stylesheet" href="https://js.arcgis.com/4.6/esri/css/main.css">
```

### 変更を反映
変更したファイルを保存してCodeCommitのGitrリポジトリに反映します。
1. Cloud9のターミナルで以下のコマンドを入力
```
$ git add .
$ git commit -m "new_config"
$ git push
```
# 動作確認
いよいよWebサイトが完成しました。Webサイトからバックエンドの処理を呼び出して正しく動くか確認しましょう。

1. AWS Consoleの検索欄に「amplify」と入力
1. AWS Amplifyのロゴをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/39ca4ce1-6e13-f03b-b982-83b19a49925c.png)
1. 前回作成したアプリを選択して左下のURLからWebサイトにアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/fa863089-6466-bc5c-3c7f-81d16ce62e1a.png)
1. Webサイトのドメインの下にある「/signin.html」にアクセスする（ブラウザのURLの末尾に「/signin.html」を追加してEnterを押してください。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/7c187156-8c5b-24e9-b4d2-e5d8f3dd51bd.png)
1. 以前作成したCognitoユーザでログインする（もしCognitoユーザがない場合はindex.htmlのGIDDY UP!ボタンから新規作成してください）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/8663b391-5f88-3a46-a911-9230192d8a59.png)
1. ride.htmlが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/e238e65b-3996-a42d-6860-9b71313d1c3d.png)
1. 地図から好きな地点をクリック（せっかくなのでここでは東京にしてみます）
1. 右上の「Request Unicorn」ボタンをクリック（赤いボタンです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/7ea94418-cdd6-5438-eedb-b4e1d3ebe392.png)

うまくいけば東京にユニコーンがやってきます。やったぜ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/c5a7489c-b31c-4153-6f6b-bb4905cc0567.png)

# まとめ
今回でAPI GatewayでWebサイトからバックエンドの処理を呼び出すことができました。
これでAWSを使って自作のWebサービスを作るための手順を一から学ぶことができました。お疲れ様でした！