curl option 覚え書き

curl コマンド、ちょくちょく使うけどオプション忘れてまう
=====

ってことで備忘録

`-o <file>`: ダウンロードしたデータをファイルとして保存
-----

long option は `--output`

curl で URL 叩いて、**_ファイル名を指定して_**ダウンロードしたいときは **小文字** の `o`。
wgetだと **大文字** の `-O` でダウンロードファイルの指定になるから毎回迷う。やってられん。
curl は **小文字** で指定。

ちなみに wget で小文字の `-o` はログファイルの指定。やってられん。

`-O`: 指定した URL の内容をそのままファイルとしてダウンロード
-----

long option は `--remote-name`
...は？

[この記事を参照してくださってた記事](https://qiita.com/KEINOS/items/7a672a415099572330d4#_reference-e5975a160f1a80365cc5
)で書いてあったオプション←

上で紹介した `-o` のように、このオプションを使ってもファイルダウンロードになる。

た・だ・し！ このオプションは _ファイル名の指定は**できない**_
代わりに、URL の末尾の名前がそのままファイル名として保存される。
また、その時最後の `/` 以降がファイル名として認識される

どういうことかと言うと、この記事を `-O` オプションを使ってダウンロードすると下のような結果になる

```shell-session
$ curl -O https://qiita.com/takayukioda/items/edf371b3566bea64d046
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 59038    0 59038    0     0   274k      0 --:--:-- --:--:-- --:--:--  274k
$ ls -l
-rw-r--r--  1 takayukioda  takayukioda  59038 Aug 28 19:58 edf371b3566bea64d046
```

予め名前がついているファイルなどのダウンロードにはこちらで十分かも？

参照していた記事にあるように、このオプションは複数のファイルダウンロードをサポートしている

```shell-session
$ curl -O http://ftp2.jp.vim.org/pub/vim/unix/vim-8.1.tar.bz2 \
       -O http://ftp.jaist.ac.jp/pub/GNU/emacs/emacs-26.1.tar.gz
```

もっと言うと上の `-o` オプションも複数ファイルのダウンロードをサポートしてる

```shell-session
$ curl -o vim.tar.bz2 http://ftp2.jp.vim.org/pub/vim/unix/vim-8.1.tar.bz2 \
       -o emacs.tar.gz http://ftp.jaist.ac.jp/pub/GNU/emacs/emacs-26.1.tar.gz
```

ちなみに wget の `-O` ではファイル名を指定しないといけない。やってられん。

`-L`: リダイレクトも追うように
-----

long option は `--location`

デフォルトでは、リダイレクト設定されている URL にアクセスした時、curl はリダイレクト先の URL に対してのリクエストを **発行しない**。
なのでリダイレクトされている場合でもデータをが欲しい場合にはこのオプションを指定する必要がある。
基本的にある程度信用できる場所へのリクエストだったら毎回付けてても良いんじゃないかな。

ただ、認証系の情報（Basic認証とかかな）はリダイレクト先の host が変わっていると送られないとかなんとか。
認証がかかってるページへアクセスする際は curl のマニュアルを見ておいたほうが良さそう。

`-d "<key-value data>"`: データの指定
-----

long option は `--data`
alias として `--data-ascii` というのもある。

このオプションを指定すると curl は POST メソッドでリクエストを送る。
ほんでもってここで指定されたデータが Request Body に入る。
`key=value` の形式で書く必要がある。

```bash
$ curl -d "token=$token"  http://some.url
```

`--data-urlencode "<key-value data>"`: 指定したデータを URL エンコードして送る
-----

`Content-Type` が `application/x-www-form-urlencoded` の時は URL エンコードしてから送らないとダメな文字があったりする。代表的なのがメールアドレスに使う **@**。URL エンコードすると `%40` に変換される。
最近の公開されている API は `application/json` に対応しているモノが多いので、あまり必要な場面は無いけれど、自社の API サーバーだと、対応していないものもあるかと思うので覚えておいて損はないはず。

`-G`: オプションをクエリパラメーターに
-----

long option は `--get`

上にあった `-d` 系のオプションは「リクエストボディに入れる」という仕様なので GET リクエストに追記してもクエリパラメターとしては設定されない。
ただ、この `-G` オプションを設定するとこの挙動が切り替わり、指定したデータがクエリパラメーターに入る。

`-c <cookie file>` & `-b <cookie file>`: Cookie の保存と利用
-----

`-c` が cookie を保存するファイルの指定
long option は `--cookiejar`

`-b` が利用する cookie ファイルの指定
long option は `--cookie`
(なぜ `b` とも思うけど、cookiejar と data で `c` も `d` も取られてたから苦肉の策なんだろうな)

APIへの認証が token じゃなくて session で管理している場合、 curl 経由でもセッションを保持したいと思うのは自然なこと。このオプションを使うとその cookie をファイルへ保存してくれるので、セッションを継続的に利用できる。

最初は相互作用で変に干渉しないかと、怖くて同時に指定するのは避けていたけど、マニュアルを見たら全然そんなことはなかった。なのでセッションを使いたかったら毎回両方とも指定しましょう。

> Users  very  often want to both read cookies from a file and write updated cookies back to a file, so using both -b, --cookie and -c, --cookie-jar in the same command line is common.

`-s`: 進捗の表示をしない
-----

long option は `--silent`

curlはダウンロードの進捗やエラーを出力してくれるけど、それが邪魔だったり shell script では別に必要なかったりする。
そんな時にこのオプションを使うと一切の進捗とエラーの表示をしなくなる。
静かすぎてちょっと怖い時もある。

`-sS`: 進捗はいらないけどエラーは表示したい
-----

long option は `--show-error`

`-S` オプションは `-s` オプションと併用することが前提のオプションで、進捗は表示されないけどエラーは表示されるようになる。
ちょっと安心。

`-H "<header info>"`: ヘッダー情報の付与
-----

long option は `--header`

OAuth のトークンとか渡すときに使うオプション。
HTTP の Request Header に情報を追加できる。

ちなみに OAuth のトークンを指定する時は

```bash
$ curl -H "Authorization: token $oauth_token" http://some.url
```

って指定する。

GitHubだけかもしれないけど。（Google とか slack ではパラメータとして指定したような気がする）


`-F "<key-value data>"`: データの指定（ファイルのアップロード等）
-----

long option は `--form`

HTTP の POST する時は複数の種類があって、 
デフォルトで使われる`application/x-www-form-urlencoded` と
ファイルアップロードで使われる `multipart/form-data`
がある。
この `-F` オプションはファイルアップロードとかをしたいときに使えるオプション。
@マークをつける事でファイルを指定できるそうな。

```bash
$ curl -F "file=@/path/to/file" http://some.url
```

詳しい内容についてはマニュアルでどうぞ :stuck_out_tongue_winking_eye: 


`-X <method>`: HTTP メソッドの指定
-----

long option は `--request`

curl は何も指定しないと GET のリクエストを発行するけど、それを変えたい時に使う。
特に PUT とか DELETE はこれで指定しないとダメなんじゃないかな。

```bash
$ curl -X PUT -d "name=update-name"  http://some.url
```

`-f`: 失敗した時に出力を出さない
-----

long option は `--fail`

Web サーバーに対してリクエストを送ってエラーが返ってくる時(403, 404, 500など)に標準出力に何も表示させないようにするオプション。
エラーの場合にエラーページの html を返される事がよくあるが、スクリプトで叩く時は正直いらない & そこで変に挙動が変わると困るといった場合に加えるオプション。
curl 経由でバイナリファイルとかを落としたい時によく見かける？

Dockerfile の中で `curl -fsL ...` という組み合わせをちょくちょく見かけている。


`-u <user:password>`: 認証用のユーザー名の設定 (デフォルトは Basic 認証)
-----

long option は `--user`

Basic 認証や Digest 認証などの認証用ユーザーを設定するためのオプション。
デフォルトでは Basic 認証用のものとして扱われる。認証の種類を表すためのオプションもあるので、「Basic認証専用」のオプションではないことに注意。

ただ単純にユーザー名を引数に渡すこともできるけど、一緒にパスワードも設定して送ることもできる。
その場合は `ユーザー名:パスワード` といった感じで `:` を間に入れて繋げてやるといい。

ちなみにユーザー名だけど引き渡すと、パスワード入力のダイアログが表示される。

プロキシにもBasic認証というものがあって、そのオプションはこれとはちょっと違うらしい。 `--proxy-basic` 

`-v`: HTTPリクエストの詳細表示
-----

long option は `--verbose`

デバッグ向けオプション。HTTP リクエストのフローを詳細に表示してくれる。

SSL の確認から HTTP リクエスト・レスポンスのヘッダーの内容まで詳細に表示してくれる。
ただし、「どんなパラメーターを実際に送ったか」は見えない。
とりあえずヘッダーのオプションを確認したい時に使う。

`--trace-ascii <file>`: どんなデータのやり取りがあるかを _ほぼ_ 全てダンプする。
-----

デバッグ向けオプション。「どんなパラメーターを実際に送ったか」まで見せてくれる。
`<file>` の部分はファイル名でもいいし `/dev/stdout` でもいい。
個人的なオススメは出力先に `/dev/stderr` して、標準出力を `/dev/null` にリダイレクト。

`curl --trace-ascii /dev/stderr https://api.example.com >/dev/null`
こうすると出力にノイズが入らなくなる。

リクエストデータ周りの出力を一部抜粋すると次のような感じ。

```
...
=> Send header, 161 bytes (0xa1)
0000: GET /api/health HTTP/2
0018: Host: api.example.com
0034: User-Agent: curl/7.54.0
004d: Accept: */*
005a: Content-Length: 20
006e: Content-Type: application/x-www-form-urlencoded
009f:
== Info: Connection state changed (MAX_CONCURRENT_STREAMS updated)!
=> Send data, 20 bytes (0x14)
0000: username=takayukioda
== Info: We are completely uploaded and fine
<= Recv header, 13 bytes (0xd)
0000: HTTP/2 200
...
```

(Host とかは誤魔化してるので、送信 byte 数とかがちょっとズレているのはご愛嬌)

ちなみに `--trace` というオプションもあって、そうすると16進数と文字列でデータを出してくれる。
APIコールのデバッグ目的ならこっちの `--trace-ascii` の方を使うと良い。

そして最後に、見出しで「ほぼ」と付けたのは `multipart/form-data` のデータはダンプしてくれないらしいから。
参考にしたページはこちら https://superuser.com/a/291456
man には特に注意は書いていなかったのと、回答があったのは2011年だから、もしかしたら curl のアップデートで対応してたりするかも。試してはいない。

`-k`: SSLの認証をスキップする
-----

long option は `--insecure`

たまにSSL認証の切れているWebページを見たい時がある。
開発用ページだったり、怖いもの見たさだったり。

curl の基本設定ではそういった SSL の認証が通らないページへのアクセスは弾かれるけど、このオプションを設定することで SSL が切れているページへのアクセスも可能になる。

`-w <format>`: 出力をカスタマイズする
-----

long option は `--write-out`

curl の出力をいい感じにカスタマイズできるオプション。
format には `%{...}` のフォーマットで変数を差し込むことができる
 (`...` 部分を curl 定義の変数名で置き換える)

変数名は `content_type`, `http_code`, `time_total` などなど
詳しくはマニュアルをどうぞ。

注意すると点として何もしなければ次の情報 **"も"** 出力される。

- curl した結果のデータ (HTMLなど)
- ダウンロードの進捗

こういった情報が邪魔であtれば `-o /dev/null`, `-s` などのオプションも加えてカスタマイズした出力だけにする必要があったりする。

それに加えてカスタマイズの出力前後は **改行されない**
必要があれば　`-w "\nstatus: %{http_code}\n"` などのように改行を加えること
シェルスクリプトで使おうとすると思わぬ落とし穴になるかもしれないのでご注意を。

とりあえずそんな感じで。


併せて読みたい
==============

[curl で作る簡易 API クライアント](https://qiita.com/takayukioda/items/8ffaa92d57d3e4bf2748)なる記事を書いてみた。
ちゃちゃっと API を試してみたいときに是非