箱のプログラミング日記。

えんじにあ奮闘記

curlの-dやら-Fやらがよく分からない

f:id:y_hakoiri:20191102121704j:plain

最近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に使用するものです。

HTTP POST - Everything curl

これはブラウザからフォームでデータを送信する時にもデフォルトで使用されるもので、エンコード済みのデータが渡されることを期待している。

つまり、エンコード未済のデータを-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

WebAPIリクエスト仕様書としてcurlコマンドのご提案 - Qiita