最近curlのPOSTリクエストでAPIの検証をすることが多いのだけど、最初数あるオプションの使い分けがいまいちよくわかっていなかったのでまとめる。
-d オプション
--data
を短く表記したもの。
フォーマット
curl -d 'name=admin&shoesize=12' http://example.com/
こうやって&でデータを羅列しても良いし、
curl -d name=admin -d shoesize=12 http://example.com/
-d
をいくつも並べて送信しても良い。
ファイルデータをそのまま渡したい場合は
curl -d @filename http://example.com
このようにすることもできる。ファイル内の改行は取り除いてくれる。
ちなみに、-d
オプションがついていればPOSTリクエストであることが明白なので-X POST
は省略可能。
Content-Typeについて
-d
オプションや--data
オプションを使用するとPOSTリクエストのContent-Typeはデフォルトで「application / x-www-form-urlencoded」が指定される。
curlの-dオプションを使用してPOSTすると、Content-Type:application / x-www-form-urlencodedのようなデフォルトのヘッダーが含まれるようになります。 これは、通常のブラウザがプレーンPOSTに使用するものです。
これはブラウザからフォームでデータを送信する時にもデフォルトで使用されるもので、エンコード済みのデータが渡されることを期待している。
つまり、エンコード未済のデータを-d
オプションで渡してはいけない。エンコード未済のデータを扱いたい場合は、--data-urlencode
オプションを使用すればエンコードしてからPOSTしてくれる。
curl --data-urlencode "name=John Doe (Junior)" http://example.com
↓エンコードして送信
name=John%20Doe%20%28Junior%29
json形式のデータを送りたいとき
先ほど書いたように-d
オプションを使用するとContent-Typeはデフォルトで「application / x-www-form-urlencoded」になる。json形式のデータを渡したい場合は明示的にしてあげなきゃいけないので
curl -d '{json}' -H 'Content-Type: application/json' https://example.com
ヘッダでContent-Typeを指定する。そうするとデフォルトの「application / x-www-form-urlencoded」ではなくこちらが優先される。
-Fオプション
-F
オプションも-d
と同じくPOSTリクエストでデータの送信ができることには変わりないのだが、
例えばブラウザにこんなフォームがある場合
<form action="submit.cgi" method="post" enctype="multipart/form-data"> Name: <input type="text" name="person"><br> File: <input type="file" name="secret"><br> <input type="submit" value="Submit"> </form>
-F
オプションは、name属性にマッチさせる形でデータを送信できる。
curl -F person=anonymous -F secret=@file.txt http://example.com/submit.cgi
-F
オプション使用時のContent-Typeはデフォルトで「multipart/form-data」が指定される。
通常、ブラウザ側で用意されたフォームによる送信の場合、Content-Typeはデフォルトで「application / x-www-form-urlencoded」が指定される。ただし、ファイルや画像の送信が含まれている場合(テキスト以外のデータが含まれている場合)は「multipart/form-data」が指定される。
同じことがcurlにも言えるので、使い分けとしては
- テキストのみ・バイナリのみなどデータの形式が一つだけの場合は
-d
を使用 - テキスト&画像データなどデータ形式が複数ある時は
-F
を使用
が良さそう。
まとめ
-d
ではContent-Typeはデフォルトで「application / x-www-form-urlencoded」が指定される- デフォルトではエンコード済みのデータが渡されることを期待しているため、エンコードしてから送信して欲しい場合は
--data-uelencode
を使用する -F
ではContent-Typeはデフォルトで「multipart/form-data」が指定される- 複数のデータ形式をまとめて送信したい場合は
-F
が適している
参考
How to HTTP with curl - Everything curl
curlのオプション--data, --data-binary, --data-raw, --data-urlencodeの違い - Qiita