API GatewayとLambdaで作るちょっとしたWebアプリケーション

# はじめにと目的
Lambdaって結局なにができるの？というところからスタートしていて、最初のうちはS3にファイルを置いたイベントを受けてリアルタイムで解析とかできるのね、ふーん、くらいの印象だった。
調べていく中でAPI Gatewayのバックエンドとして動くことがわかり、じゃあ実際どのくらいのことができるのかを知りたくなり、テストとしてマイクロブログ(といってもただ書いたことが保存されるだけ)を実装した。

それにあたっての手順などをせっかくなのでまとめて記載する。

タイトルに「ちょっとした」とつけたのは自分がAPI GatewayやLambdaどころか、AWSに対する知見があまりにも少なく、かつ今回はスケーラビリティに関する試験を行っていないためである。


# 構成
## 構成イメージ
最終的にはこんな感じになった。
(ここにたどり着くまでに紆余曲折を経ているが、ただの苦労話なので、その点については本文書には記載しない)

![graph.jpg](https://qiita-image-store.s3.amazonaws.com/0/99704/42ab7666-1860-25e2-aeca-20d34d4827b6.jpeg "graph.jpg")

# 構築
## 注意事項
- 色々作業はしたが、簡単だったり、新しさがないことはこの文書では省略する。
- また、作成したコードも大したものを書いていない上新しさもないので、内容には言及しない。

## コンテンツサーバ
### S3
- コンテンツ提供用のS3 bucketの作成
- 作成したbucketの公開Web設定

### Route 53
- 作成したS3 bucketの名前が引けるよう設定する。
- ドメインを持っていなければそのままでも良いかもしれない。

## 実際の処理の作成
ここでは投稿された文章を登録する、というところに絞って構築の手順を記載する。

### API Gateway
ここでAPIを定義する。
今回例えば、投稿するというAPIを下記のように設計するとしたとする。
POST http://api-endpoint/post

その場合の設定は下記のようになる。

![スクリーンショット 2015-12-26 8.51.20.png](https://qiita-image-store.s3.amazonaws.com/0/99704/5d3a6799-f400-7fd8-4d46-4259df161ccf.png "スクリーンショット 2015-12-26 8.51.20.png")

手順としては

- postリソースを作成する
- postリソースへPOSTメソッドを割り当てる

となる。
この段階では処理を記述していないので、一旦は「Mock Integration」で作成してある。

### Lambda

ここでは作成したコードについては言及しない。
サンプルなので特に大したことはないという意味でもあるが、Lambdaではblueprintにたくさんのサンプルがあるため、それを改変すれば十分に作成できると考えているためである。
(普段ほとんどコードを書かない私でも1時間もあればとりあえず動くものは作成できた)

さて、さっそくLambdaのコンソールより作業をはじめると、はじめに「Select blueprint」なる画面がでてくる。
ここで、dynamoと検索すれば今回下敷きに使えるblueprintが出てくるのでこれを利用すると簡単である。
下記画像2つ目のmicroservice-http-endpointを利用した。
![スクリーンショット 2015-12-26 9.00.35.png](https://qiita-image-store.s3.amazonaws.com/0/99704/b5bf819a-7a5a-832f-0a9d-263d8bc508c3.png "スクリーンショット 2015-12-26 9.00.35.png")

続いての「configuration」画面では基本的には画面に従えば問題ない。
一点だけ注意すると、RoleではDynamoDBの操作ができるものを選択する必要がある。
そのため、特にRoleを作成していない場合は「Basic with DynamoDB」を選択してガイドに従えば良い。

![スクリーンショット 2015-12-26 9.04.05.png](https://qiita-image-store.s3.amazonaws.com/0/99704/e7f4a224-d38f-71aa-4050-ce62b084e749.png "スクリーンショット 2015-12-26 9.04.05.png")

### API GatewayとLambdaの連携
これも非常に単純である。新しく作る場合はガイドに従えば良いし、そうでなくすでに作成してある場合は下記の様に設定を変更できる。

画面右のほうにある「Integration Request」をクリックし、
![スクリーンショット 2015-12-26 9.12.44.png](https://qiita-image-store.s3.amazonaws.com/0/99704/6ca1da25-ef29-7c53-5a9d-518739795a71.png "スクリーンショット 2015-12-26 9.12.44.png")

「Integration type」を「Lambda Function」に変更し、「Lambda Region」、「Lambda Function」を設定する。

![スクリーンショット 2015-12-26 9.13.39.png](https://qiita-image-store.s3.amazonaws.com/0/99704/e87a6033-3ed6-76ba-4ee3-b16ccf93ff2a.png "スクリーンショット 2015-12-26 9.13.39.png")

## コンテンツからAPIの呼び出し
### APIのデプロイ
API Gatewayの設定が完了したら、APIをデプロイするという手順が必要である。
下記の様に行う。

まず、「Deploy API」をクリックする。
![スクリーンショット 2015-12-26 9.17.45.png](https://qiita-image-store.s3.amazonaws.com/0/99704/6ee7bb1f-4d0f-e1a6-809a-455f994c5bc4.png "スクリーンショット 2015-12-26 9.17.45.png")

表示された画面の「Deployment stage」をはじめてならNew Stage、2回め以降なら適切なStageを選択し、「Deploy」を押すことで実際にAPIが利用できるようになる。
![スクリーンショット 2015-12-26 9.18.55.png](https://qiita-image-store.s3.amazonaws.com/0/99704/be29a01e-d016-a82b-69fe-2752f8d42df2.png "スクリーンショット 2015-12-26 9.18.55.png")

ちなみにデフォルトで、APIは全世界公開となるはずなので、作って適当に放置し、迷惑なアクセスを受けると面倒なので、適切に公開を行うこと。

Invoke URLと言う箇所が実際に呼び出すAPIのエンドポイントとなる。
![スクリーンショット 2015-12-26 9.22.30.png](https://qiita-image-store.s3.amazonaws.com/0/99704/1323d77a-a537-15fc-aaa5-ba7ebd1b24e0.png "スクリーンショット 2015-12-26 9.22.30.png")

さて、この段階ではコンテンツサーバとAPIサーバのドメインが別れてしまい、AJAXによる通信が行えない。
そのため、ドメインを同じにするか、CORSを有効にする必要がある。
ドメインを同じにするのはやり方を調べてないので、今回はCORSを有効にする方法を下記に記す。

まず、CORSを有効にしたいリソースを選択したうえで、「Enable CORS」をクリックする。
![スクリーンショット 2015-12-26 9.24.39.png](https://qiita-image-store.s3.amazonaws.com/0/99704/6272c7ef-527b-c53f-1ede-587d4de1c15c.png "スクリーンショット 2015-12-26 9.24.39.png")

必要な設定がいろいろ出てくるのでサラッと流しながら最下部の「Enable CORS and replace...」をクリックする。
![スクリーンショット 2015-12-26 9.29.13.png](https://qiita-image-store.s3.amazonaws.com/0/99704/f9c2cb09-252c-0f24-5c79-ae0b139d25c7.png "スクリーンショット 2015-12-26 9.29.13.png")

これでクロスドメインでAPI Gatewayで作成したAPIが呼べるようになりました！

### AJAXでAPIの呼び出し
ここではjQueryを利用した呼び出しのサンプルを下記に記載する。
(書いてみたものの、ただのjQueryのサンプルだった。)

```js
function getPost() {
     $.ajax({
        url: "https://XXXXXX.execute-api.ap-northeast-1.amazonaws.com/development/post",
        method: "GET",
        success: function (ev) { ... }
    });
}
```

# 感想
個人的にはほとんどドキュメントを見ないで操作できてしまい、かつ、こんなに簡単に公開Webサービスが作れてしまいそうなことには驚いた。
ちょっとしたものなら一からsinatraとか使って作ってるよりも、サービス使ったほうが簡単だし、コストもサーバ借りるより安そうだし良さそうに見える。

サーバを作るのも好きだし、コードを書くのも好きだから、EC2を借りてその上でゴリゴリやるというのは本来大変好きなことなのでその作業を省くのは若干つまらないところもある。
とはいえ実際問題、Webアプリケーションは作って公開して終わりではなく、その後の運用を考えると実は結構障壁が大きく、特に個人レベルだとおいそれと作って公開ということがしにくいように思っていたので、コードのみ考えれば良いこういうサービスは特に運用者を用意しにくい環境では有用だと思う。

ただそれだけであればHerokuのようなPaaSで十分だったりするが、国内にサーバがなかったり、AWSに比べてそこまで流行っていない(印象)なので、ドキュメントがあまりないとか色々問題があるように思っている。
何より、最初API Gatewayもしくは一般的なPaaSで作成していて、ある程度大きくなってきてカスタム要素が増えたから個別のサーバに、と考えた時に、一般的なPaaS事業者はEC2のようななサーバを持っていないから完全に別サービスへの移行が必要になる。
一方で今回の構成のようにバックエンドをDynamoDBとかにしておけばそこのデータ移行は基本不要となり、アプリケーションだけ移設すれば良いように思う。
やはり、IaaSとPaaSが同じサービスセットとして提供されていて、それぞれから同じコンポーネントを利用できるというAWSのアーキテクチャが良く出来ているなぁと感じた。

(AWSもPaaSも素人なので間違いあればご指摘ください)

# 参考
- [Amazon API Gateway を独自ドメインで利用する](http://dev.classmethod.jp/cloud/aws/api-gateway-with-custom-domain/)