NASA APOD API で cURL コマンドを使ってみる

# 目次
1. 背景
2. cURLとは
3. 準備
4. なぜcURLを使うのか？
5. API リクエストの送信
6. cURL コマンドのオプション
7. curlと他のCLIコマンドを組み合わせる
8. APIコールに便利なツール
9. jsonデータを見やすくする
10. ブラウザからcURLコマンドを作成

# 1. 背景
[弊社のテックブログ](https://tech.iimon.co.jp/p/7abdd6ca-5cab-4d41-8319-e8d2613ab794)でcURLについて紹介されていたので、復習の為です。

IBMの記事がありましたのでこちらを和訳したり、追記してまとめます。
https://developer.ibm.com/articles/what-is-curl-command/

# 2. cURL とは
- client URLの略です。
- 開発者がサーバーとの間でデータを転送するために使用するコマンドラインツールです。
- URLの形で場所と送信したいデータを指定することで、サーバーと会話することができます。
- cURLはHTTPやHTTPSを含むいくつかの異なるプロトコルをサポートしており、ほとんどすべてのプラットフォームで動作します。

cURLの最も基本的なコマンドは以下です。
```terminal
curl http://example.com
```

# 3. 準備
[NASA APOD（Astronomy Picture Of the Day）API](https://api.nasa.gov/)を使って、いくつかの例を作成します。
上のリンクにアクセスして、API Keyを作成して下さい。

# 4.なぜ cURL を使うのか？
- ほとんどのオペレーティングシステムや接続デバイスと互換性があります。
- エンドポイントが動作しているかどうかをテストするのに便利です。
- 正確に何が送信/受信されたかの詳細を提供するため、デバッグに役立ちます。
- エラーログが充実しています。
- レート制限が可能です。

# 5. API リクエストの送信
cURLを使用してAPIリクエストを送信することができます。
各リクエストは、通常、以下の4つの主要な部分で構成されています：

1. エンドポイント(endpoint)：これは、リクエストを送信するアドレス（URL）です。

2. HTTPメソッド(HTTP method)：最も一般的に使用されるメソッドは、GET、POST、PUT、DELETEです。
    - GET：サーバーからリソースを取得するために使用されます。これは、ファイル、情報、画像などの取得に使われることが多いです。
    - POST：情報をサーバーに送信するために使用されます。
    - PUT：リソースを作成または更新するために使用されます。これは、データベースにレコードを作成または更新するためや、ファイルの内容を更新するために使用されることがあります。
    - DELETE：データベースのエントリなどのリソースを削除するために使用されます。
これらのメソッドのアクションは推奨されるアクションですが、具体的に何が起こるかはAPIの仕様や実装によって定義されます。

3. ヘッダー(Headers)：これは、コンテンツタイプ、ユーザーエージェントなどのリクエストに関するメタデータを含みます。
4. ボディ(Body)：これはメッセージボディであり、送信したいデータを含んでいます（もしあれば）。通常、ボディはPOSTとPUTメソッドで使用されます。

# 6. cURL コマンドのオプション
cURLには200を超えるオプションがあります。
ターミナルで curl -h を入力することで、その一部を確認することができます。
最も一般的に使用されるコマンドオプションには、以下のようなものがあります：

-I は HTTPSヘッダーのみを返します。
```terminal
curl --request GET 'https://api.nasa.gov/planetary/apod?api_key=<myapikey>&date=2020-01-01' -I

HTTP/2 200 
date: Sun, 01 Oct 2023 15:50:22 GMT
content-type: application/json
content-length: 1512
vary: Accept-Encoding
access-control-allow-origin: *
access-control-expose-headers: X-RateLimit-Limit, X-RateLimit-Remaining
age: 0
strict-transport-security: max-age=31536000; includeSubDomains; preload
vary: Accept-Encoding
via: http/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
x-api-umbrella-request-id: <x-api-umbrella-request-id>
x-cache: MISS
x-ratelimit-limit: 2000
x-ratelimit-remaining: 1998
x-vcap-request-id: <x-vcap-request-id>
x-frame-options: DENY
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
```

-v は詳細表示オプションです。

```terminal
curl --request GET 'https://api.nasa.gov/planetary/apod?api_key=$NASA_API_KEY&date=2020-01-01' -v
```

接続からヘッダー、返されるデータまで、cURLコマンドを実行したときに起こるすべてのことを表示します。

-o は出力をファイルに保存するオプションです

```terminal
curl --request GET 'https://api.nasa.gov/planetary/apod?api_key=$NASA_API_KEY&date=2020-01-01' --output curloutput

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1512  100  1512    0     0   2953      0 --:--:-- --:--:-- --:--:--  2982

```

curloutputというファイルに出力されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/bc3353b9-b90c-9e0e-04de-2a46574e4ebc.png)

# 7. curlと他のCLIコマンドを組み合わせる
cURLを他のコマンドラインインターフェースのコマンドと組み合わせることは、コマンドの出力をcURLコマンドの入力として、またはその逆として使用したい場面で非常に便利です。

例として、cURLとgrepを使って、特定のテキストがウェブページに含まれているかどうかを調べることができます。

以下は、cURLとPythonを使用して、NASA APIへのリクエストから画像のリンクを抽出し、それをPreviewアプリ（MacOS専用）で表示する例です。

```terminal
curl --request GET "https://api.nasa.gov/planetary/apod?api_key=$NASA_API_KEY&date=2023-10-01" -s | python3 -c "import sys, json; print(json.load(sys.stdin)['url'])" | xargs curl -o NASApicture.jpg && open -a Preview NASApicture.jpg
```

### コマンドの説明

```terminal
-s
```
- --silentの短縮形。
- このオプションを使用すると、curlはエラーや進捗情報を表示しないので出力がクリーンになります。

```terminal
python3 -c "import sys, json; print(json.load(sys.stdin)['url'])
```
- python3 -c: Python3を用いて、次に続く文字列内のコードを実行します。
- import sys, json: Pythonのsysとjsonモジュールをインポートします。
- print(json.load(sys.stdin)['url']): 標準入力からJSONを読み込み、そのJSONオブジェクトのurlキーに対応- する値（画像のURL）を出力します。
- このPythonコードの部分は、入力として受け取ったJSONからurlキーの値を抽出して出力します。

```terminal
|
```
- パイプです。
- 左側のコマンドの出力を右側のコマンドの入力として渡します。

```terminal
xargs curl -o NASApicture.jpg
```
- xargs: 前のコマンド（Pythonスクリプト）からの出力（画像のURL）を引数として次のコマンドに渡します。
- curl -o NASApicture.jpg: curlコマンドを使用してURLからデータを取得し、-oオプションで指定されたファイル名（この場合はNASApicture.jpg）に保存します。

この部分は、前のPythonコードで抽出した画像のURLを使って画像をダウンロードします。

```terminal
&&
```
左側のコマンドが成功した場合にのみ右側のコマンドを実行します。

```terminal
open -a Preview NASApicture.jpg
```
macOSのopenコマンドを使用して、-aオプションで指定されたアプリケーション（この場合はPreviewアプリ）でファイルを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/afb128b5-887f-283e-5016-2beff805a30b.png)

# 8. APIコールに便利なツール
HTTPie、Postman、VS CodeのRest Clientなど、APIとやりとりするためのさまざまなツールを使うことができます。

## 8.1 HTTPie
HTTPieは、ユーザーフレンドリーであると評価されているコマンドラインのHTTPクライアントです。また、より表現豊かで色分けされたUIが含まれています。[オンライン版](https://httpie.io/cli/run)も提供しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/73e6fb0e-f9f4-bffe-6e85-9fa24fd994e7.png)


## 8.2 Postman
PostmanはAPI開発に関連する全てのことのためのUIベースのクライアントで、おそらく最も人気のあるものの一つです。Postmanは非常に強力です。

Postmanの中からcURLコマンドを生成・実行することができます。cURLコマンドを生成するには、リクエストURLとパラメータを入力し、その後、右側にあるコードオプションをクリックします。
![スクリーンショット 2023-10-02 1.56.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/06030479-2e96-1577-7ec5-095051a45de2.png)

curlを含むいくつかの言語から選択できるボックスが表示されます。curlを選択すると、生成されたcurlコマンドが表示されます。
![スクリーンショット 2023-10-02 2.00.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/7b21d072-6140-e709-bbda-23a9aab07784.png)

Postmanは作成したすべてのリクエストの履歴を提供し、それらにさえ日付スタンプを付けます。
これは、APIで作業する際にデータポイントや参照を収集するのに便利です。
それをクライアントがあなたのためにノートを取ってくれるようなものだと考えてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/867b64af-0cda-ba95-1c50-436174fe1f8b.png)

## 8.3 Rest Client in VS Code
- VS CodeのRest Clientは、cURLコマンドを実行するためのツールの中で人気の一つです。
- 軽量で、良好な構文ハイライトがあります。
- VS Code内から手早くcURLリクエストを行うための非常に役立つアドオンです。

### 使い方
1. Rest Client をinstall
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/ba5a78fb-3c44-51d7-b3b1-094274e5d83b.png)

2. .httpファイルにすることで使用できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/a01f127b-b70e-773c-db5b-5f68f6721a2e.png)

# 9. jsonデータを見やすくする
brew install jqでjqをインストールして、| jqを追加すると、jsonデータを見やすく表示してくれます。
```terminal
~ $ curl --request GET 'https://api.nasa.gov/planetary/apod?api_key=5Q73YVl6dk4fImsjZlyowShPKwEPteOIhRZn763w&date=2020-01-01' | jq               
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1512  100  1512    0     0   3043      0 --:--:-- --:--:-- --:--:--  3066
{
  "date": "2020-01-01",
  "explanation": "Why is Betelgeuse fading?  No one knows.  Betelgeuse, one of the brightest and most recognized stars in the night sky, is only half as bright as it used to be only five months ago.  Such variability is likely just  normal behavior for this famously variable supergiant, but the recent dimming has rekindled discussion on how long it may be before Betelgeuse does go supernova.  Known for its red color, Betelgeuse is one of the few stars to be resolved by modern telescopes, although only barely.  The featured artist's illustration imagines how Betelgeuse might look up close. Betelgeuse is thought to have a complex and tumultuous surface that frequently throws impressive flares.  Were it to replace the Sun (not recommended), its surface would extend out near the orbit of Jupiter, while gas plumes would bubble out past Neptune.  Since Betelgeuse is about 700 light years away, its eventual supernova will not endanger life on Earth even though its brightness may rival that of a full Moon.  Astronomers -- both amateur and professional -- will surely continue to monitor Betelgeuse as this new decade unfolds.    Free Presentation: APOD Editor to show best astronomy images of 2019 -- and the decade -- in NYC on January 3",
  "hdurl": "https://apod.nasa.gov/apod/image/2001/BetelgeuseImagined_EsoCalcada_2662.jpg",
  "media_type": "image",
  "service_version": "v1",
  "title": "Betelgeuse Imagined",
  "url": "https://apod.nasa.gov/apod/image/2001/BetelgeuseImagined_EsoCalcada_960.jpg"
}

```

# 10. ブラウザからcURLコマンドを作成
cURL としてコピーを押すと、cURLコマンドを作成できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/867bfc29-9cb7-54a6-e96d-aa2d6de2f213.png)

# 参考
- [What is cURL and how does it relate to APIs?](https://developer.ibm.com/articles/what-is-curl-command/)
- [curlコマンドでHTTPリクエストを投げてみる](https://tech.iimon.co.jp/p/7abdd6ca-5cab-4d41-8319-e8d2613ab794)
- [curl コマンド 使い方メモ](https://qiita.com/yasuhiroki/items/a569d3371a66e365316f)