初心者備忘録　POSTするAPIをAWS API GWで作る

##はじめに
こんにちは、高知で勉強している森田ドラゴンです。
インターンでPOST APIを作成する課題をやっているのですが、正直、POST APIどころかGETのAPIについても理解が曖昧です。
なので、POST APIを AWS API GWとLambdaを使用して作成しながら、勉強していきます。

##前知識
###APIとは
https://qiita.com/NagaokaKenichi/items/df4c8455ab527aeacf02
このサイトが参考になるかと。
>厳格な定義はないが、広義にはHTTPプロトコルを用いてネットワーク越しに呼び出すアプリケーション間、システム間のインターフェースのこと。

うむむ、わかったようなわからないような。
僕の中では、なんらかのサービスが提供している、データをやりとりするプログラム
という風な認識をしています

###RESTとは
APIと調べると確実に出てくるこの単語。
このサイトが参考になります。
https://qiita.com/TakahiRoyte/items/949f4e88caecb02119aa
REpresentational State Transfer　(直訳すると 代表的な状態変換？)の略で、APIの設計手法の１つです。

RESTは設計に際し以下を設計原則とするよう提言されています。

- アドレス指定可能なURIで公開されていること
- インターフェース(HTTPメソッドの利用)の統一がされていること
- ステートレスであること
- 処理結果がHTTPステータスコードで通知されること

ここら辺は設計規則なので、そういうものだと納得しておきます。

ただ、なんでREST でやった方がいいんですかね？
https://qiita.com/masato44gm/items/dffb8281536ad321fb08
ここに答えが書いてありました

> RESTなAPIはリソースに基づいて、処理が決まる

なるほど！つまりURLに対応づけて処理を決めようとしていた、僕のAPIはRESTじゃなかったっていうことですね。
RESTなAPIは、例えばユーザー情報等に紐づいて、.../user/1 のようなURLになるみたいです

リソースベースでAPIを作っておけば「将来的に機能を拡張する際に、URLが大量に作られてしまう」なんていう問題も回避できそうですね。

ステートレス故に、アクセスの多いSNSのAPIの設計に役立つ〜という話もありましたが、APIを設計したことがないので、いまいちピンときてません。ここら辺は経験ですね。

###POSTとGET
「API GW チュートリアル ~ 」みたいに調べるとgetでデータを送るやり方が出てきますが、POSTでデータを送るやり方はいまいちヒットしません(調べ方が悪い + POSTでのデータの送り方がわかってない)

POSTとGETの違いは何でしょうか？両方ともデータをフロントからサーバに送る仕組みです。

- GET urlにデータを付加して送る
- POST メッセージボディにデータを付加して送る

GETはURLに付加されるので、送信したデータが見えます。Googleで検索すると、URLに検索キーワードが表示されるのをイメージしてもらえればいいかと思います。

POSTのメッセージボディは、HTTPリクエストを構成する3つの要素の１つです。

###HTTPリクエスト
HTTPリクエストは以下の3つの要素から成り立っています。

- 開始行
- ヘッダー
- 本文

この本文がメッセージボディとも呼ばれます。
開始行はHTTPメソッドやURLを定義しています。HTTPヘッダーは、クライアントやサーバーがリクエストやレスポンスで追加情報を渡すことを可能にします。

本文、メッセージボディにはPOST等で送信されるデータが付加されます。
具体的には、htmlで作られた入力フォームから送信される情報が、メッセージボディに付加されます。他にも、URLに付加されるリソースでは送りきれないデータを送る際に定義され、送信されるみたいです。

つまり、POST APIを作りたければ、API GWで メッセージボディを操作する方法を探せということです。データが遅れさえすれば、加工は簡単そうです。

参考
https://developer.mozilla.org/ja/docs/Web/HTTP/Messages

##実際に作ってみる
では実際に作ってみます。チュートリアルがないと思ってたんですけど、公式にあったので、これを利用します。https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-create-api-from-example.html

###1. Create APIから Exampleを洗濯して作成
![Screen Shot 2019-10-28 at 17.41.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288717/780bc535-96c3-74e6-401f-9df866ec0390.png)

##2. APIの画面を理解する
![Screen Shot 2019-10-28 at 22.26.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288717/81ba11ed-dd9c-b092-e5d1-3c8c586de774.png)

APIを作成し、POST/petsを開くとこんな画面がでてきます。この画面について詳しく説明してくれていますが、いまいちピンとこないので、噛み砕いていきます。

>選択した (POST /pets) メソッドで結果として表示される [メソッドの実行] ペインには、メソッドの構造と動作の論理的なビューが表示されます。

これはこの画面のことです。意味のまま、論理的な構成が表示されています

>[Method Request] および [メソッドレスポンス] は、API のフロントエンド (クライアント) を含む API のインターフェイスであるのに対し、[統合リクエスト] および [統合レスポンス] は、バックエンド (http://petstore-demo-endpoint.execute-api.com/petstore/pets) を含む API のインターフェイスです。

これもそのままの意味ですね。[メソッド~]はフロント側から見たリクエストとレスポンスを定義しています。

> クライアントは、API を使用して [メソッドリクエスト] からバックエンド機能にアクセスします。API Gateway は、必要に応じてクライアントリクエストを [統合リクエスト] のバックエンドで許容される形式に変換してから、受信リクエストをバックエンドに転送します。

ふむふむ、統合リクエストのセクションで、バックエンドに渡せるデータに変換する感じですね。

>変換されたリクエストは、統合リクエストと呼ばれます。同様に、バックエンドは API Gateway へのレスポンスを [統合レスポンス] で返します。次に、API Gateway はこれを [メソッドレスポンス] にルーティングしてから、クライアントに送信します。また、API Gateway は、必要に応じて、バックエンドのレスポンスデータをクライアントで予期される形式にマッピングします。

まとめると、以下のようです。

- メソッドリクエスト: フロントから渡されるリソースの定義
- 統合リクエスト: リソースをバックエンドで許容できるように変換
- メソッドレスポンス: フロントに渡されるレスポンスを定義(ステータスコード)
- 統合レスポンス: クライアントで許容できるように変換

つまり、統合セクションで、データの形式を変換しろということみたいです。
今回はリクエストとして、json形式でデータを送るので、統合リクエストで処理することはなさそうです。

##3.テスト
![Screen Shot 2019-10-28 at 23.37.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288717/ea39fc4f-a9ca-c381-77d5-ddab2fbf3928.png)
リクエストボディ-に
    {"type": "dog","price":249.99}
と入力し、テストをクリックするとこのような結果が。これではつまらないので、デプロイしてみます。

##4. デプロイ
![Screen Shot 2019-10-29 at 0.04.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288717/acc4a59b-faa9-8c44-5866-79821ebcdf74.png)
デプロイして出てきたurlを curlで叩きます。

```bash
(apiのurl)test/pets/ -d "{\"type\": \"dog\",\"price\": 249.99}" -H "Content-Type:application/json"
```
```bash
#結果
{
  "pet": {
    "type": "dog",
    "price": 249.99
  },
  "message": "success"
}
```
デプロイしても、テストと同じ結果が帰ってきました。
ちなみにcurl してあげるときはjsonのデータのダブルクォーテーションを\でエスケープしてあげる必要があります。

##感想
過去から引き継がれてる通信方式が、現在どのように利用されているのかが、わからないので、毎回モヤモヤしています。色々チュートリアルを試して経験を積みたいです。