API通信の理解を深めよう！〜Curlを使用してHTTPリクエスト・レスポンスを理解する〜

# API通信
API は「Application Programming Interface」の略称。
APIを使用すると、2つの異なるソフトウェアが相互に通信できます。
API通信の使用例として、URLRequestを渡して、Responseを受け取り、JSON形式からSwift形式にデコードして、Viewに表示することなどに使います。
使用したことはあるけど、API通信の裏側で何が行われているのか？:thinking:という疑問解消するべく、調べてみました！
# Curlを使用してみよう！
## Curlとは
Curlとは、コマンドラインからHTTPリクエストを送信するためのオープンソースのライブラリやツールのことです。また返ってきたHTTPレスポンスを表示することができます。
CurlはAPIテストにおいて重要なツールとして広く利用されています。

## コマンドラインからCurlを使用する！
ターミナルを開き、次のコマンドラインを入力し。Curlをインストールする！
```
$ brew install curl
```
インストールに成功したかどうか次のコマンドで確認できます。
```
$ curl　--version
```
今回は下記のURLのOpen Weather APIを使用しました。

https://openweathermap.org/current

早速Curlを使用してHTTPリクエストを送信してみよう！
[APIKey]はご自身で取得してください。
今回は東京の緯度と経度を設定しました。
```
$ curl -i 'https://api.openweathermap.org/data/2.5/weather?lat=35.689753&lon=139.691731&appid=[APIkey]'
```
※URLを「'(シングルクォーテーション)」で囲っていなかったら、「zsh: parse error near `&'」とエラーが返ってくるので注意。
上手くいくと下記のようなHTTPレスポンスが表示されます。
```
HTTP/1.1 200 OK
Server: openresty
Date: Fri, 24 Nov 2023 00:50:28 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 468
Connection: keep-alive
X-Cache-Key: /data/2.5/weather?lat=35.69&lon=139.69
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST

{"coord":{"lon":139.6917,"lat":35.6895},
"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],
"base":"stations",
"main":{"temp":293.33,"feels_like":292.76,"temp_min":290.4,"temp_max":295.23,"pressure":1005,"humidity":52},
"visibility":10000,"wind":{"speed":7.2,"deg":200},
"clouds":{"all":0},
"dt":1700786398,
"sys":{"type":2,"id":268395,"country":"JP","sunrise":1700774721,"sunset":1700811025},
"timezone":32400,"id":1850144,"name":"Tokyo","cod":200}%
```
## HTTPレスポンスの解読
レスポンスメッセージは下記のように大きく3つに分けることができます。
### ①ステータスライン
```
HTTP/1.1 200 OK
```
プロトコルバージョンは最新のHTTP/1.1であり、
ステータスコードの200 OKは、リクエストが成功したことを表します！

### ②ヘッダ

```
Server: openresty
Date: Fri, 24 Nov 2023 00:50:28 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 468
Connection: keep-alive
X-Cache-Key: /data/2.5/weather?lat=35.69&lon=139.69
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST
```
⚫︎Server: openresty
レスポンスを生成したサーバーで使用されたソフトウェアを説明
⚫︎Date: Fri, 24 Nov 2023 00:50:28 GMT
メッセージを生成した日時
⚫︎Content-Type: application/json; charset=utf-8
JSON形式のデータをUTF-8でエンコードしている
⚫︎Content-Length: 468
ボディの長さを示している。
⚫︎Connection: keep-alive
現在のトランザクションが完了したあとも、ネットワーク接続を開いたままにするかどうかを制御する。もし送信された値が keep-alive であった場合は、接続が維持される。
⚫︎X-Cache-Key: /data/2.5/weather?lat=35.69&lon=139.69
リクエストを送信するコマンドを繰り返し、キャッシュする。
⚫︎Access-Control-Allow-Origin: *
資格情報がないリクエストでは、リテラル値 "*" を指定する。この値はブラウザーに、すべてのオリジンからのリクエストコードにリソースへのアクセスを許可するように指示する。
⚫︎Access-Control-Allow-Credentials: true
リクエストの資格情報モードがtrueの場合、資格情報の許可。
⚫︎Access-Control-Allow-Methods: GET, POST
GET, POSTのHTTPメソッドのみリソースにアクセスを許可。
作成、読み込みを許可。


⚫︎CRUDとHTTPメソッドの対応
|CRUD名|意味|メソッド|
|:---|:---|:--|
|Create|作成|POST/PUT|
|Read|読み込み|GET|
|Update|更新|PUT|
|Delete|削除|DELETE|

③ボディ
```
{"coord":{"lon":139.6917,"lat":35.6895},
"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],
"base":"stations",
"main":{"temp":293.33,"feels_like":292.76,"temp_min":290.4,"temp_max":295.23,"pressure":1005,"humidity":52},
"visibility":10000,"wind":{"speed":7.2,"deg":200},
"clouds":{"all":0},
"dt":1700786398,
"sys":{"type":2,"id":268395,"country":"JP","sunrise":1700774721,"sunset":1700811025},
"timezone":32400,"id":1850144,"name":"Tokyo","cod":200}%
```
ボディにJSON形式のAPIレスポンスが返ってきている。これをデコードしてSwift形式にしてAPI通信で使っている。
# おまけ：間違ったHTTPリクエストをしてレスポンスを見てみる
経度に存在しない値を入れて、リクエストしてみる。lon=ひなっこ
```
curl -i 'https://api.openweathermap.org/data/2.5/weather?lat=35.689753&lon=ひなっこ&appid=[APIkey]'
```
HTTPリクエストを見てみる。
```
HTTP/1.1 400 Bad Request
Server: openresty
Date: Fri, 24 Nov 2023 09:19:25 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 41
Connection: keep-alive
X-Cache-Key: /data/2.5/weather?lat=35.69&lon=
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST

{"cod":"400","message":"wrong longitude"}%  
```
ステータスコード400 Badは、リクエストの構文パラメータの間違いを示します。
ボディでもステータスコード400と経度の間違いと表示されています。

# 参考文献

https://gblogs.cisco.com/jp/2021/08/whats_rest-api_basic/

https://apidog.com/jp/blog/curl-user-guide/

https://gihyo.jp/book/2010/978-4-7741-4204-3


https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Server

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Connection

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Access-Control-Allow-Methods