はい、承知いたしました。API連携に必須である curl
コマンドを用いたJSONデータのPOST送信に関する詳細な解説記事を、約5000語で記述します。
API連携に必須!curlでJSONをPOSTする実践テクニック – 詳細解説
はじめに:なぜAPI連携とcurl
、そしてJSONなのか?
現代のシステム開発において、API(Application Programming Interface)連携は不可欠な要素となっています。異なるシステム間でデータをやり取りし、機能を連携させることで、より複雑で強力なアプリケーションを構築することが可能になります。Webサービスの連携、マイクロサービスの通信、モバイルアプリケーションのバックエンド連携など、その用途は多岐にわたります。
API連携の主要な手段の一つが、HTTPプロトコルを介したデータ交換です。特に、クライアントがサーバーに対してデータを送信する際には、HTTPのPOSTメソッドが頻繁に利用されます。そして、その送信されるデータの形式として、JSON(JavaScript Object Notation)はデファクトスタンダードと言えるほど広く普及しています。軽量で人間が読み書きしやすく、多くのプログラミング言語で容易に扱えるため、構造化されたデータをAPIでやり取りするのに最適なのです。
このようなAPI連携の現場において、開発者やエンジニアにとって強力な味方となるのが curl
コマンドです。curl
は、URL構文を用いてデータを転送するためのコマンドラインツールであり、HTTP, HTTPS, FTPなど様々なプロトコルをサポートしています。特に、API連携のテスト、デバッグ、あるいは簡単なバッチ処理やスクリプト内でのAPI呼び出しにおいて、curl
はその手軽さと柔軟性から絶大な威力を発揮します。
ブラウザや専用のGUIツール(Postman, Insomniaなど)もAPI操作には便利ですが、curl
には以下のような利点があります。
- 環境を選ばない: ほとんどのOS(Linux, macOS, Windows)に標準搭載または容易にインストール可能。
- 軽量: 起動が速く、リソース消費が少ない。
- スクリプト親和性: シェルスクリプトやバッチファイルに組み込みやすい。
- 自動化: 定期的なタスクやCI/CDパイプラインでのAPI呼び出しに利用可能。
- 詳細な制御: ヘッダー、認証、タイムアウトなど、HTTPリクエストのあらゆる側面を細かく制御できる。
- デバッグ:
-v
オプションなどで通信の詳細を確認しやすく、問題特定に役立つ。
この記事では、curl
を使ってJSONデータをHTTP POSTリクエストとして送信する、API連携における最も基本的かつ重要なテクニックに焦点を当て、その詳細を徹底的に解説します。単にコマンドの書き方を説明するだけでなく、なぜそのオプションが必要なのか、どのような挙動をするのか、よくある落とし穴や解決策、さらには実践的なシナリオでの応用方法まで、網羅的にカバーします。
この記事を読み終える頃には、あなたは curl
を使って自信を持ってJSON POSTリクエストを操り、API連携の様々な場面でそのスキルを活かせるようになっているでしょう。
curl
の基本とHTTP POSTリクエストの構造
JSON POSTの詳細に入る前に、curl
の基本的な使い方と、HTTP POSTリクエストがどのような構造になっているかを確認しておきましょう。
curl
コマンドの基本的な使い方
curl
コマンドの基本的な構文は以下のようになります。
bash
curl [オプション...] <URL>
最も単純な例は、GETリクエストで特定のURLからコンテンツを取得することです。
bash
curl https://example.com
これにより、指定したURLのウェブページのHTMLソースが表示されます。
HTTPメソッドの種類とPOSTの役割
HTTPプロトコルでは、クライアントがサーバーに対してどのような操作を行いたいかを指示するために「メソッド」を使用します。主なメソッドには以下のようなものがあります。
- GET: 指定したリソースの表現を取得します。データの取得に用いられ、リクエストボディは通常伴いません。
- POST: 指定したリソースにデータを送信し、そのリソースに対する処理を要求します。新しいリソースの作成や、フォームデータの送信などに使われます。JSONデータをAPIに送信する際の主要なメソッドです。
- PUT: 指定したURIにリクエストボディを保存します。既存リソースの更新や、新しいリソースの作成に使われます(クライアントがURIを指定する場合)。
- DELETE: 指定したリソースを削除します。
- PATCH: リソースの部分的な更新を行います。
API連携において、クライアントがサーバーにデータを送信して新しいレコードを作成したり、既存レコードを更新したり、あるいは特定の処理をトリガーしたりする場合に、POSTメソッドが最もよく利用されます。
HTTP POSTリクエストの構造
HTTP POSTリクエストは、大きく分けて以下の要素で構成されます。
- リクエストライン: メソッド(POST)、パス、HTTPバージョンなどが含まれます。
POST /api/users HTTP/1.1
- ヘッダー: リクエストに関する様々なメタデータを提供します。例えば、送信するデータの種類(
Content-Type
)、認証情報(Authorization
)、クライアントの情報(User-Agent
)などが含まれます。各ヘッダーはHeader-Name: Header-Value
の形式で記述されます。
Host: api.example.com
Content-Type: application/json
Content-Length: 123
Authorization: Bearer your_token - リクエストボディ: サーバーに送信したい実際のデータが含まれます。POSTリクエストの最も重要な部分であり、JSONデータはこの部分に格納されます。
curl
を使ってPOSTリクエストを送信する場合、デフォルトではGETリクエストになるため、-X POST
オプションを使って明示的にメソッドを指定する必要があります。ただし、後述する-d
や --data
といったオプションを使う場合は、curl
は自動的にメソッドをPOSTに設定するため、-X POST
は省略可能です。しかし、明示性を高めるために -X POST
を付けることも推奨されます。
JSONデータの準備
curl
でPOSTするJSONデータは、通常、文字列としてコマンドラインに直接記述するか、ファイルに保存しておき、それをcurl
に読み込ませる方法があります。どちらの方法を選択するかは、JSONデータのサイズ、複雑さ、再利用性の必要性によって判断します。
JSONフォーマットの基本
JSONは、キーと値のペアの集まり(オブジェクト {}
)や、値の順序付きリスト(配列 []
)で構成されます。値としては、文字列、数値、真偽値(true/false)、null、オブジェクト、配列が使用可能です。
例:シンプルなユーザーオブジェクト
json
{
"username": "tech-user",
"email": "[email protected]",
"isActive": true,
"roles": ["reader", "writer"]
}
このJSONデータをcurl
で送信可能な形式で準備する必要があります。
JSONデータを文字列として準備する
コマンドラインに直接記述する場合、JSON文字列全体をシングルクォートまたはダブルクォートで囲みます。JSON内部でクォートが必要な場合は、外側のクォートの種類に合わせてエスケープする必要があります。
- シングルクォートで囲む場合: JSON内部のダブルクォート
"
はそのまま記述できます。JSON内部にシングルクォート'
が含まれる場合は、\'
のようにエスケープが必要ですが、JSONではキーや文字列リテラルにシングルクォートは通常使用しないため、このケースは稀です。 - ダブルクォートで囲む場合: JSON内部のダブルクォート
"
は\"
のようにバックスラッシュでエスケープする必要があります。JSON内部にバックスラッシュ\
が含まれる場合も\\
とエスケープが必要です。
例:シングルクォートで囲む
json
'{ "name": "John Doe", "age": 30 }'
例:ダブルクォートで囲む(内部のダブルクォートをエスケープ)
json
"{ \"name\": \"John Doe\", \"age\": 30 }"
一般的に、JSON文字列は内部にダブルクォートを多用するため、外側をシングルクォートで囲む方法がシェルでのエスケープが少なくて済むため、より推奨されます。ただし、シェルによってはシングルクォート内のバックスラッシュの扱いが異なる場合があるため、注意が必要です。
JSONデータをファイルとして準備する
より複雑なJSONデータや、何度も同じデータを送信する場合、JSONデータを.json
などの拡張子を持つテキストファイルに保存するのが効率的です。
例:data.json
というファイルにJSONを保存
json
{
"product_id": "A123",
"name": "Laptop",
"price": 1200.00,
"tags": ["electronics", "computer", "portable"]
}
この方法の利点は、JSONデータ自体をシェルから独立して管理できるため、エスケープの問題が解消され、可読性が高まることです。
curl
でJSONをPOSTする基本
いよいよcurl
を使ってJSONデータをPOST送信する方法を具体的に見ていきましょう。主要なオプションは -X POST
、-H
、そして -d
または --data
です。
Content-Type: application/json
ヘッダーの重要性
APIにJSONデータを送信する際、最も重要なヘッダーの一つが Content-Type
です。これは、リクエストボディに含まれるデータの形式をサーバーに伝える役割を果たします。JSONデータを送信する場合は、必ず Content-Type: application/json
を指定する必要があります。サーバーはこのヘッダーを見て、受信したリクエストボディをJSONとしてパースしようとします。このヘッダーを付け忘れると、サーバーはリクエストボディを正しい形式で解釈できず、エラーになる可能性が高いです。
curl
でヘッダーを指定するには、-H
オプションを使用します。
bash
-H "Content-Type: application/json"
-H
オプションは複数指定できるため、他のヘッダー(認証情報など)も同時に指定できます。
bash
-H "Content-Type: application/json" -H "Authorization: Bearer your_token"
リクエストボディを送信する -d
/ --data
オプション
curl
でリクエストボディを含めてPOSTリクエストを送信するには、-d
または --data
オプションを使用します。これらのオプションは、指定されたデータをリクエストボディとして含め、さらに以下の処理を自動的に行います。
- HTTPメソッドをPOSTに設定します(
-X POST
は省略可能になりますが、明示のため付けても構いません)。 - リクエストヘッダーに
Content-Type: application/x-www-form-urlencoded
を追加します。
注: -d
や --data
を使うと、デフォルトで application/x-www-form-urlencoded
が付加されます。JSONを送信する場合は、このデフォルトの Content-Type
を application/json
で上書きする 必要があります。したがって、JSON POSTでは -d
と -H "Content-Type: application/json"
はセットで使うのが基本となります。
-d
オプションには、送信したいデータを文字列として直接渡すか、ファイルから読み込むかを指定できます。
簡単なJSONデータを直接 -d
で送信する例
最も基本的なJSON POSTの例です。JSONデータを文字列として -d
オプションに渡します。
bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"id": 101, "status": "active"}' \
https://api.example.com/items
解説:
* -X POST
: HTTPメソッドとしてPOSTを明示的に指定します(-d
を使う場合は省略可能ですが、推奨)。
* -H "Content-Type: application/json"
: リクエストボディのデータ形式がJSONであることをサーバーに伝えます。これがJSON POSTには必須です。
* -d '{"id": 101, "status": "active"}'
: リクエストボディとして送信するJSONデータを指定します。ここではシングルクォートで囲んでおり、JSON内部のダブルクォートはそのままです。
* https://api.example.com/items
: リクエストの送信先URLです。
このコマンドは、指定したURLに対してJSONデータを含むPOSTリクエストを送信します。
ファイルからJSONデータを読み込んで -d
で送信する例 (@filename
)
前述のように、JSONデータが複雑な場合やファイルとして管理したい場合は、-d
オプションに @
記号とファイル名を続けて指定することで、ファイルの内容をリクエストボディとして読み込ませることができます。
まず、JSONデータをファイルに保存します。例:request_body.json
json
{
"name": "New Product",
"description": "This is a description of the new product.",
"price": 99.99,
"is_available": true,
"attributes": {
"color": "red",
"size": "M"
},
"tags": ["new", "featured", "sale"]
}
そして、curl
コマンドでこのファイルを指定します。
bash
curl -X POST \
-H "Content-Type: application/json" \
-d @request_body.json \
https://api.example.com/products
解説:
* -d @request_body.json
: request_body.json
ファイルの内容を読み込み、それをリクエストボディとして送信します。この方法を使えば、ファイル内のJSONデータにシェルによるエスケープは不要です。
この方法は、JSONデータが大きくなったり、特殊文字(シェルにとって意味を持つ文字)を含む場合に特に有効です。
実践テクニック:複雑なJSONデータとファイルからの送信
JSONデータが複雑になったり、動的に生成される場合、シェルからの直接入力には限界が出てきます。ここでは、より実践的なJSONデータの扱い方と、-d
以外の関連オプションについて解説します。
エスケープ処理の必要性と <<EOF
(ヒアドキュメント)
JSON文字列を直接-d
に渡す場合、JSON内部の文字がシェルにとって特別な意味を持つ文字(例えば $
, ``,
`, "
など)である場合、適切にエスケープしないと予期せぬエラーや挙動を引き起こす可能性があります。
例:JSON内にシェルの変数展開に使われる可能性がある文字を含む場合
json
{
"message": "Hello $user!",
"path": "C:\\temp\\data"
}
これをシングルクォートで囲む場合、$
はシェルによって変数展開されようとする可能性があります。ダブルクォートで囲む場合は $
や \
をエスケープする必要があります。
“`bash
シェルによって $user が展開される可能性がある
curl -X POST -H “Content-Type: application/json” -d ‘{“message”: “Hello $user!”, “path”: “C:\temp\data”}’ https://api.example.com/send
ダブルクォートで囲む場合は $ と \ をエスケープ
curl -X POST -H “Content-Type: application/json” -d “{\”message\”: \”Hello \$user!\”, \”path\”: \”C:\\temp\\data\”}” https://api.example.com/send
“`
このようなエスケープの複雑さを避けるために、以下の方法がよく使われます。
- ファイルに保存 (
-d @filename
): 最も推奨される方法。ファイルの内容はシェルに解釈されないため、エスケープは不要です。 - ヒアドキュメント (
<<EOF
): シェルスクリプト内で複数行の文字列を扱う際に便利な機能です。ヒアドキュメントを使うと、複数行のJSONデータをエスケープなし(または最小限のエスケープ)でcurl
に渡すことができます。
ヒアドキュメントを使った例:
“`bash
read -r -d ” json_data << EOF
{
“message”: “Hello $user! This is a multi-line message.”,
“data”: [
1,
2,
3
],
“settings”: {
“enabled”: true,
“limit”: 100
}
}
EOF
ここで $user 変数はシェルによって展開されますが、json_data 変数全体がシェルに解釈されるのを防ぐために ‘EOF’ をクォートすることもできます。
read -r -d ” json_data << ‘EOF’ # こちらの場合、$user はそのまま文字列として保持されます。
curl -X POST \
-H “Content-Type: application/json” \
-d “$json_data” \
https://api.example.com/process
“`
解説:
* read -r -d '' json_data << EOF ... EOF
: ヒアドキュメントを使って、複数行のテキストを json_data
という変数に格納します。
* read -r
: バックスラッシュによるエスケープを無効にします。
* -d ''
: 区切り文字を空文字列に設定し、入力の最後まで(ここでは EOF
マーカーまで)を読み込みます。
* << EOF
: ヒアドキュメントの開始を示し、デリミタとして EOF
を使用します。続く行が EOF
だけの行が現れるまで json_data
変数に読み込まれます。
* << 'EOF'
: デリミタをシングルクォートで囲むと、ヒアドキュメント内の変数展開やコマンド置換が無効になります。JSONデータにシェルの特殊文字が含まれていても、そのままの文字列として扱いたい場合にこちらを使います。
* -d "$json_data"
: 変数に格納されたJSONデータを -d
オプションに渡します。変数をダブルクォートで囲むことで、変数内の改行などが保持されます。
ヒアドキュメントはシェルスクリプト内で動的にJSONを生成したり、長いJSONを手作業で入力する場合に便利ですが、ファイルを使う方法に比べるとやや記述が複雑になります。
--data-binary
/ --data-raw
オプション
-d
/ --data
オプションは、デフォルトでデータをURLエンコードし、Content-Type: application/x-www-form-urlencoded
をセットします。しかし、JSONデータはURLエンコードする必要がなく、また application/json
ヘッダーが必要です。前述の例では -H "Content-Type: application/json"
で上書きしていますが、-d
のデフォルト挙動は少し不自然です。
curl
には、リクエストボディの扱い方をより細かく制御するためのオプションがあります。
--data-binary
: 指定されたデータをバイナリとして、つまり一切変更せずに(URLエンコードせずに)リクエストボディとして送信します。-d
と同様に、-X POST
を自動的に設定しますが、Content-Type
は自動で設定しません。JSONデータを送信する際に、エスケープなどの変換をされたくない場合に適しています。--data-raw
:--data-binary
と似ていますが、入力の先頭にある@
を特別扱いせず、単なる文字列として扱います。こちらもURLエンコードせず、Content-Type
も自動設定しません。
JSON POSTにおいては、-d
に -H "Content-Type: application/json"
を組み合わせる方法が最も一般的で広く使われています。しかし、データの変更(特に改行や特殊文字の扱い)を防ぎたい場合は --data-binary
の方がより意図に合っていると言えます。
--data-binary
を使った例:
bash
curl -X POST \
-H "Content-Type: application/json" \
--data-binary @request_body.json \
https://api.example.com/products
bash
curl -X POST \
-H "Content-Type: application/json" \
--data-binary '{"message": "Hello\nWorld!"}' \
https://api.example.com/greet
この例では、\n
がそのままリクエストボディに含まれます。-d
の場合はシェルやcurl
の処理によっては \n
が実際の改行文字に変換される可能性があります。
--data-raw
を使った例:
“`bash
“@file.json” という文字列自体をリクエストボディとして送りたい場合(通常は稀)
curl -X POST \
-H “Content-Type: application/json” \
–data-raw ‘@file.json’ \
https://api.example.com/raw_data
“`
JSON POSTにおいては、ほとんどの場合 -d @filename
か -d '...'
+ -H "Content-Type: application/json"
の組み合わせで十分です。ただし、バイナリデータ(例えばBase64エンコードされた画像データなど)をJSON内に含めて送信するような、より厳密なデータ転送が必要な場合は --data-binary
が有効な選択肢となります。
API連携に必須の追加オプション
実際のAPI連携では、単にJSONをPOSTするだけでなく、認証、エラーハンドリング、デバッグ、ネットワーク設定など、様々な要素を考慮する必要があります。curl
はこれらの要件を満たすための豊富なオプションを提供しています。
ヘッダーの操作 (-H
を複数回使う)
APIは、Content-Type
以外にも様々なヘッダーを要求することがあります。認証情報 (Authorization
)、APIキー、リクエストの追跡ID (X-Request-ID
)、ユーザーエージェント (User-Agent
) などです。これらのヘッダーはすべて -H
オプションを繰り返して指定します。
bash
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_access_token" \
-H "X-Correlation-ID: abc-123-xyz" \
-d '{"action": "process", "data": {"value": 123}}' \
https://api.example.com/process_data
不要なヘッダーを削除したい場合は、ヘッダー名にコロンだけを付けて指定します。例えば、デフォルトで送られる可能性のある Accept:
ヘッダーを削除したい場合などです。
bash
curl -H "Accept:" ... # Accept ヘッダーを送信しない
認証オプション
多くのAPIは、リクエストを行ったクライアントを識別し、権限をチェックするために認証を要求します。curl
は様々な認証方法をサポートしています。
-
Basic認証 (
-u
,--user
): ユーザー名とパスワードをusername:password
の形式でBase64エンコードしてAuthorization: Basic ...
ヘッダーとして送信します。bash
curl -X POST \
-H "Content-Type: application/json" \
-u "myuser:mypassword" \
-d '{"message": "secure data"}' \
https://api.example.com/secure/dataパスワードをコマンドラインに平文で書きたくない場合は、パスワード部分を省略すると
curl
が実行時に入力プロンプトを表示します。bash
curl -u "myuser:" ... # 実行時にパスワード入力が求められる -
Bearerトークン (OAuth 2.0などで一般的):
Authorization: Bearer <token>
ヘッダーとしてトークンを送信します。これはカスタムヘッダーとして-H
で指定します。bash
ACCESS_TOKEN="your_actual_access_token"
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{"action": "do_something"}' \
https://api.example.com/resource -
APIキー: APIキーは、カスタムヘッダーとして送信されることもあれば、クエリパラメータとして送信されることもあります。仕様に合わせて
-H
または URL に直接記述して指定します。“`bash
ヘッダーとして送信する場合
curl -X POST \
-H “Content-Type: application/json” \
-H “X-API-Key: YOUR_API_KEY” \
-d ‘{“data”: “payload”}’ \
https://api.example.com/serviceクエリパラメータとして送信する場合
curl -X POST \
-H “Content-Type: application/json” \
-d ‘{“data”: “payload”}’ \
“https://api.example.com/service?api_key=YOUR_API_KEY”
“`
タイムアウトと接続設定
APIが応答しない場合や遅延している場合に、curl
がいつまで待つかを制御できます。スクリプトなどでAPIを呼び出す場合に、無限に待機するのを防ぐために重要です。
--connect-timeout <seconds>
: TCP接続が確立されるまでの最大時間を指定します。-m <seconds>
,--max-time <seconds>
: リクエスト全体(接続、データ送信、レスポンス受信)にかかる最大時間を指定します。この時間を超えると、curl
は処理を中断します。
“`bash
接続試行は10秒まで、リクエスト全体は30秒まで待つ
curl -X POST \
–connect-timeout 10 \
-m 30 \
-H “Content-Type: application/json” \
-d ‘{“key”: “value”}’ \
https://api.example.com/slow_endpoint
“`
-
--retry <num>
: 一時的なエラー(例: 5xx系ステータスコード)が発生した場合に、指定された回数だけリクエストを再試行します。“`bash
最大3回再試行する
curl –retry 3 …
“`
進捗表示と詳細出力 (-v
, -i
, -s
)
APIの挙動を確認したり、デバッグしたりする際に、curl
の出力オプションは非常に役立ちます。
-
-v
,--verbose
: リクエストとレスポンスの詳細な情報を表示します。送信しているヘッダー、受信したヘッダー、接続情報などがstderrに出力されます。デバッグ時にはほぼ必須のオプションです。bash
curl -X POST \
-v \
-H "Content-Type: application/json" \
-d '{"test": true}' \
https://api.example.com/debug出力例(一部):
“`
* Added api.example.com:443:XX.XX.XX.XX to DNS cache
* About to connect() to api.example.com port 443 (#0)
* Trying XX.XX.XX.XX…
* Connected to api.example.com (XX.XX.XX.XX) port 443 (#0)POST /debug HTTP/1.1
Host: api.example.com
User-Agent: curl/7.54.0
Accept: /
Content-Type: application/json
Content-Length: 14- upload completely sent off: 14 out of 14 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Mon, 23 Oct 2023 10:00:00 GMT
< Content-Length: 25
< - Connection #0 to host api.example.com left intact
{“status”: “success”, “data”: {}} # <= レスポンスボディ
“`
- upload completely sent off: 14 out of 14 bytes
-
-i
,--include
: レスポンスヘッダーも一緒に表示します。デフォルトではレスポンスボディのみが表示されます。HTTPステータスコードや、レスポンスのContent-Type
などを確認したい場合に便利です。bash
curl -X POST \
-i \
-H "Content-Type: application/json" \
-d '{"key": "value"}' \
https://api.example.com/items出力例(一部):
“`
HTTP/1.1 201 Created
Content-Type: application/json
Location: /items/102
Date: Mon, 23 Oct 2023 10:05:00 GMT
Content-Length: 30{“id”: 102, “message”: “Created”} # <= レスポンスボディ
“` -
-s
,--silent
: 進捗メーターやエラーメッセージなど、curl
自身の進行状況に関する出力を抑制します。スクリプトでAPIのレスポンスだけを取得したい場合などに使用します。エラーが発生しても標準エラー出力にも何も出なくなるため、スクリプトでのエラーチェックには注意が必要です(後述の--fail
を併用するなど)。bash
curl -s ... # 静かに実行 -
--fail
: HTTPステータスコードが400以上の場合(クライアントエラーまたはサーバーエラー)、エラーメッセージを表示せず、curl
を非ゼロの終了コードで終了させます。スクリプトでAPI呼び出しの成功・失敗を判定する際に非常に役立ちます。-s
と一緒に使うことで、成功時は何も出力せず、失敗時もcurl
自体のエラーメッセージは出さずに、スクリプト側で終了コードをチェックするという使い方ができます。bash
if ! curl -s --fail -X POST ... > response.json; then
echo "API call failed!" >&2
exit 1
fi
HTTPS/SSL証明書の検証
ほとんどのAPIはセキュリティのためにHTTPSを使用しています。curl
はデフォルトでSSL証明書の検証を行います。これは、接続先が信頼できるサーバーであることを確認するために重要です。
しかし、開発環境やテスト環境で自己署名証明書を使用している場合など、検証を無効にしたい場面があるかもしれません。その場合は -k
, --insecure
オプションを使用します。
“`bash
証明書検証をスキップ (注意: 本番環境では使用しないこと!)
curl -X POST \
-k \
-H “Content-Type: application/json” \
-d ‘{“data”: “test”}’ \
https://dev.api.example.com/unsafe_test
“`
警告: -k
オプションはセキュリティリスクを高めます。接続先サーバーのなりすましなどの攻撃に対して無防備になるため、本番環境やインターネット上のサービスに対しては 絶対に 使用しないでください。信頼できるCA(認証局)が発行した証明書を使用し、curl
のデフォルトの検証機能を活用してください。必要であれば --cacert
オプションでカスタムCA証明書を指定することも可能です。
プロキシ設定
企業ネットワーク内など、インターネットにアクセスするためにプロキシサーバーを経由する必要がある環境では、curl
にプロキシ設定を指定する必要があります。
-
-x <proxyhost>:<proxyport>
,--proxy <proxyhost>:<proxyport>
: 使用するプロキシサーバーを指定します。bash
curl -X POST \
-x http://proxy.example.com:8080 \
-H "Content-Type: application/json" \
-d '{"key": "value"}' \
https://api.example.com/items
プロキシ認証が必要な場合は、-U <user>:<password>
オプションを使用します。
より高度な利用法
JSON POSTの基本的な操作だけでなく、レスポンスの処理やスクリプトへの組み込みなど、より応用的な使い方を見ていきましょう。
レスポンスの処理
APIからのレスポンスは、通常JSON形式で返されます。このレスポンスボディをファイルに保存したり、さらに処理したりしたい場合があります。
-
ファイルへの保存 (
-o
,-O
):-o <filename>
: レスポンスボディを指定したファイル名で保存します。-O
: レスポンスを受けるURLのファイル名部分を使ってファイル名として保存します。POSTリクエストではあまり使いません。
“`bash
レスポンスを results.json というファイルに保存
curl -X POST \
-H “Content-Type: application/json” \
-d ‘{“query”: “status”}’ \
https://api.example.com/report > results.jsonまたは -o オプションを使う
curl -X POST \
-H “Content-Type: application/json” \
-d ‘{“query”: “status”}’ \
-o results.json \
https://api.example.com/report
``
>
**注:** 標準出力へのリダイレクトと
-oは同じ効果をもたらしますが、
-oは
curl自体がファイル書き込みを行うのに対し、
>はシェルの機能です。通常はどちらでも構いませんが、複雑なパイプラインの一部として
curl` を使う場合は考慮が必要な場合があります。 -
jq
などのツールとの連携: APIのレスポンス(JSON)から特定のデータを抽出したり、整形したりする場合、jq
のようなコマンドラインJSONプロセッサーが非常に強力です。curl
の出力をパイプ|
でjq
に渡して処理します。“`bash
レスポンスから特定のキーの値だけを抽出
curl -s -X POST \
-H “Content-Type: application/json” \
-d ‘{“user_id”: 123}’ \
https://api.example.com/user/profile \
| jq ‘.data.email’例: {“data”: {“id”: 123, “name”: “Test User”, “email”: “[email protected]”}} というレスポンスの場合、”[email protected]” が出力される
レスポンスJSONを整形して表示
curl -s -X POST \
-H “Content-Type: application/json” \
-d ‘{“long_data”: […]}’ \
https://api.example.com/complex_response \
| jq ‘.’ # または jq .
``
jqを使う際は、
curlに
-s(silent) オプションを付けて、
curl自身の余分な出力を抑制するのが一般的です。これにより、標準出力にはAPIからのレスポンスボディ(JSON)だけが出力され、
jq` がそれを正確に処理できます。
POST以外のメソッドでのJSON送信 (PUT, PATCH)
JSONデータはPOSTだけでなく、PUTやPATCHリクエストのリクエストボディとしてもよく使われます。例えば、既存リソースの全体更新(PUT)や部分更新(PATCH)です。
これらのメソッドでJSONを送信する場合も、基本的な考え方はPOSTと同じです。-X
オプションでメソッドを指定し、-H "Content-Type: application/json"
ヘッダーを付け、-d
や --data-binary
でJSONデータを渡します。
“`bash
PUT リクエストで既存リソースを更新
curl -X PUT \
-H “Content-Type: application/json” \
-d ‘{“id”: 101, “status”: “inactive”, “reason”: “manual_override”}’ \
https://api.example.com/items/101
PATCH リクエストで既存リソースの一部を更新
curl -X PATCH \
-H “Content-Type: application/json” \
-d ‘{“status”: “pending_review”}’ \
https://api.example.com/items/101
“`
スクリプト内での利用
curl
はシェルスクリプトやバッチファイルに組み込みやすいのが大きな利点です。スクリプト内で curl
を使う場合、以下の点に注意するとより堅牢な処理が実現できます。
-
変数と組み合わせる: JSONデータの一部を動的に変数から埋め込んだり、URLやヘッダーを変数で管理したりします。前述のヒアドキュメントを使った例や、以下のように
printf
などでJSON文字列を生成して変数に格納し、それを-d "$variable"
で渡す方法があります。“`bash
ITEM_ID=105
NEW_STATUS=”completed”
JSON_PAYLOAD=$(printf ‘{“id”: %d, “status”: “%s”}’ “$ITEM_ID” “$NEW_STATUS”)curl -X POST \
-H “Content-Type: application/json” \
-d “$JSON_PAYLOAD” \
https://api.example.com/update_item
“` -
終了コードの確認:
curl
は実行結果を示す終了コード(exit status)を返します。成功時は通常0、失敗時は非ゼロの値となります。特に--fail
オプションを付けている場合、HTTPステータスコードがエラー(4xx, 5xx)なら非ゼロを返します。スクリプトではこの終了コードをチェックして、API呼び出しの成功・失敗を判定し、適切な後続処理やエラーハンドリングを行います。“`bash
API呼び出しを実行し、終了コードを確認
-s
で出力を抑制し、--fail
でHTTPエラーを終了コードに反映させるRESPONSE_FILE=$(mktemp) # 一時ファイルを作成
if ! curl -s –fail -X POST \
-H “Content-Type: application/json” \
-d ‘{“query”: “status”}’ \
-o “$RESPONSE_FILE” \
https://api.example.com/report; thenecho “Error: API call failed with status code.” >&2 # エラーメッセージを標準エラー出力へ
rm “$RESPONSE_FILE” # 一時ファイルを削除
exit 1 # スクリプトを終了
fi成功した場合、レスポンスファイルを処理
cat “$RESPONSE_FILE” | jq ‘.’
rm “$RESPONSE_FILE”
“`$?
シェル変数で直前のコマンドの終了コードを取得できます。bash
curl ...
if [ $? -ne 0 ]; then
echo "curl command failed." >&2
# エラー処理...
exit 1
fi -
エラーメッセージのリダイレクト:
curl
は進行状況やエラーメッセージを標準エラー出力 (stderr) に出力します。スクリプトの通常の出力(標準出力, stdout)と分けたい場合や、エラーログにリダイレクトしたい場合は、2>
や&>
を使用します。“`bash
標準出力はファイルに、標準エラー出力は画面に表示
curl -s –fail … > response.json 2>&1 # この例ではエラーも標準出力に行くので注意
標準出力はファイルに、標準エラー出力は別のファイルに
curl -s –fail … > response.json 2> error.log
標準出力だけファイルに、標準エラー出力は捨てる (非推奨)
curl -s –fail … > response.json 2>/dev/null
“`
よくある落とし穴と解決策
curl
でJSON POSTを行う際、初心者が陥りやすい一般的な問題とその解決策をまとめます。
-
Content-Type: application/json
ヘッダーの忘れまたは間違い:- 問題: サーバーがリクエストボディをJSONとして認識できず、パースエラーや不正なリクエストとして処理される。
- 解決策: 常に
-H "Content-Type: application/json"
オプションを含めることを確認する。特に-d
オプションを使用する場合は、デフォルトのapplication/x-www-form-urlencoded
を上書きするために必須。
-
JSONフォーマットの間違い(構文エラー):
- 問題: JSON文字列として無効な形式(例: カンマの抜け、引用符のエラー、不要な末尾カンマなど)。サーバー側でJSONパースエラーが発生する。
- 解決策:
- JSONデータをファイルに保存し (
-d @filename
)、エディタやjq .
、オンラインのJSONバリデーターなどで事前に構文チェックを行う。 - コマンドラインに直接記述する場合は、エスケープ漏れや引用符の対応に細心の注意を払う。複雑なJSONはファイル化を検討する。
- JSONデータをファイルに保存し (
-
シェルによるエスケープや変数展開の問題:
- 問題: JSONデータ内の特殊文字(
"
、\
、$
、“`など)がシェルによって誤って解釈され、意図しないデータが送信される。 - 解決策:
- JSONデータをファイルに保存し、
-d @filename
または--data-binary @filename
を使用する。これが最も安全で簡単な方法。 - コマンドラインに直接記述する場合は、JSON全体をシングルクォートで囲み、JSON内のダブルクォートはエスケープしない。
- ヒアドキュメントを使う場合は、デリミタをシングルクォートで囲む (
<< 'EOF'
) ことで変数展開などを抑制できる。
- JSONデータをファイルに保存し、
- 問題: JSONデータ内の特殊文字(
-
認証情報の不足または間違い:
- 問題: APIが認証を要求しているのに認証情報(Basic認証、Bearerトークン、APIキーなど)を送信していない、または間違っている。サーバーから401 Unauthorizedまたは403 Forbiddenエラーが返される。
- 解決策: APIのドキュメントを確認し、必要な認証方法と情報を正確にヘッダーまたはURLに含める。
-v
オプションを使って、実際に送信されているヘッダーを確認する。
-
HTTPメソッドの間違い:
- 問題: データを送信したいのにGETメソッドになっている、またはPOST以外のメソッド(PUT, PATCHなど)を使うべきところでPOSTを使っている。サーバーから405 Method Not Allowedなどのエラーが返される。
- 解決策:
-X POST
や-X PUT
のように、正しいHTTPメソッドを明示的に指定する。-d
や--data
を使う場合は自動的にPOSTになるが、明示は推奨。
-
URLの間違い:
- 問題: ホスト名、ポート番号、パス、クエリパラメータなどに間違いがある。サーバーが見つからない、または目的のエンドポイントに到達できない。
- 解決策: URLを注意深く確認する。ホスト名の解決に問題がある場合は、ネットワーク設定やDNSを確認する。
-
ネットワークの問題(ファイアウォール、プロキシ):
- 問題: 企業のファイアウォールがAPIエンドポイントへのアクセスをブロックしている、またはプロキシ設定が必要なのに設定していない。
curl
が接続エラー(Could not resolve host, Connection refused, Operation timed outなど)になる。 - 解決策: ネットワーク管理者に確認し、必要なポートが開いているか、プロキシ設定が必要かを確認する。プロキシが必要な場合は
-x
オプションで設定する。
- 問題: 企業のファイアウォールがAPIエンドポイントへのアクセスをブロックしている、またはプロキシ設定が必要なのに設定していない。
-
API側のエラーレスポンスの読み取り方:
- 問題: APIからエラー(4xx, 5xx系のステータスコード)が返ってきたが、
curl
の出力だけでは原因が特定しにくい。 - 解決策:
-i
オプションでレスポンスヘッダー(特にステータスコード)を確認する。-v
オプションでリクエストとレスポンスの詳細を確認する。- レスポンスボディにエラーの詳細がJSONなどで含まれていることが多い。
jq .
でレスポンスボディを整形して確認する。APIドキュメントでエラーレスポンスの形式を確認する。
- 問題: APIからエラー(4xx, 5xx系のステータスコード)が返ってきたが、
-
リダイレクトの自動追跡:
- 問題: APIエンドポイントがリダイレクト(3xxステータスコード)を返すが、
curl
がデフォルトではそれを追跡しないため、期待したレスポンスが得られない。 - 解決策:
-L
,--location
オプションを付けると、curl
はリダイレクト先を自動的に追跡してくれます。
- 問題: APIエンドポイントがリダイレクト(3xxステータスコード)を返すが、
これらの落とし穴を事前に把握し、-v
, -i
, --fail
などのデバッグオプションを効果的に活用することで、問題の特定と解決がスムーズに行えます。
実践例:具体的なAPI連携シナリオ
ここまで学んだテクニックを使って、いくつかの具体的なAPI連携シナリオを想定した curl
コマンドの例を見てみましょう。
シナリオ1:Webhookのテスト
開発中のアプリケーションが外部サービスからのWebhookを受け取るエンドポイントを持っているとします。そのエンドポイントがJSON形式のPOSTデータを受け取る場合、curl
を使って擬似的なWebhookリクエストを送信し、アプリケーションの動作をテストできます。
エンドポイント: http://localhost:8080/webhook
期待するJSONデータ:
json
{
"event_type": "user.created",
"timestamp": "2023-10-23T10:30:00Z",
"data": {
"user_id": "usr_abcdef123",
"email": "[email protected]",
"name": "Test User"
}
}
curl
コマンド:
bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"event_type": "user.created",
"timestamp": "2023-10-23T10:30:00Z",
"data": {
"user_id": "usr_abcdef123",
"email": "[email protected]",
"name": "Test User"
}
}' \
http://localhost:8080/webhook
さらに:
* アプリケーション側でのリクエスト受信を確認するために -v
オプションを付けると、送信したヘッダーやボディ、サーバーからの応答ヘッダー(HTTPステータスコードなど)を確認できます。
* JSONデータが複雑なら、ファイルに保存して -d @webhook_payload.json
とします。
* APIキーやシグネチャなどの認証情報が必要な場合は、-H
オプションで追加します。
シナリオ2:認証が必要な外部APIへのデータ登録
認証(Bearerトークン)が必要な外部APIに、新しい商品を登録するシナリオです。
APIエンドポイント: https://api.external-service.com/v1/products
認証方式: Authorization: Bearer
送信するJSONデータ (new_product.json
):
json
{
"name": "Wireless Mouse",
"sku": "WM-001",
"price": 25.99,
"currency": "USD",
"stock": 150,
"description": "Ergonomic wireless mouse with long battery life."
}
curl
コマンド:
“`bash
ACCESS_TOKEN=”your_very_secret_token_here”
curl -X POST \
-H “Content-Type: application/json” \
-H “Authorization: Bearer $ACCESS_TOKEN” \
–data-binary @new_product.json \
“https://api.external-service.com/v1/products” \
-v # デバッグのために詳細出力も有効にする
“`
さらに:
* レスポンスとして登録された商品のIDなどが返される場合が多いです。jq
を使ってそのIDを抽出・表示できます。
```bash
# ... 上記curlコマンド ... \
# 省略 ... https://api.external-service.com/v1/products" \
# -s を付けて curl 自身の進行状況出力を抑制し、レスポンスボディのみをパイプに渡す
| jq '.product.id'
```
- 登録に失敗した場合(例: 400 Bad Request, 401 Unauthorized, 500 Internal Server Error)、
-v
や-i
オプションの出力、または--fail
オプションによる終了コードのチェックがデバッグに役立ちます。
シナリオ3:スクリプトでの定期的なデータ送信
バッチ処理として、データベースから抽出したデータを整形してJSON形式でAPIに定期的に送信するスクリプトを作成するシナリオです。
シェルスクリプトの例 (send_data.sh
):
“`bash
!/bin/bash
API_URL=”https://api.internal-service.com/ingest”
API_KEY=”your_internal_api_key”
DATA_FILE=”data_to_send.json” # 前処理で生成されたJSONファイル
送信するJSONデータの例 (実際は data_to_send.json の内容)
{ “records”: [ { … }, { … } ], “timestamp”: “…” }
APIコール実行
-s: サイレントモード (進捗バーなど非表示)
–fail: HTTPエラーを終了コードに反映
-o /dev/null: 標準出力(レスポンスボディ)を捨てる (必要に応じてファイルに保存や jq で処理)
2>&1 | tee api_call.log: 標準エラー出力(curlのエラーメッセージ)を標準出力にまとめてログファイルにも出力
if ! curl -s –fail -X POST \
-H “Content-Type: application/json” \
-H “X-API-Key: $API_KEY” \
–data-binary @”$DATA_FILE” \
“$API_URL” 2>&1 | tee api_call.log; then
echo “$(date) – Error sending data to API. Check api_call.log” >&2
exit 1 # スクリプトをエラー終了
else
echo “$(date) – Data successfully sent to API.”
# 送信成功後の処理 (例: 元データファイルをアーカイブするなど)
# …
exit 0 # スクリプトを正常終了
fi
“`
このスクリプトでは、--data-binary @
でファイルからJSONを読み込み、APIキーをヘッダーで送信しています。--fail
オプションでAPIからのHTTPエラーを検出可能にし、エラーが発生した場合はログを出力してスクリプトを終了させています。成功時は正常終了します。これをcronなどで定期実行することで、バッチ処理としてAPI連携を実現できます。
curl
以外の選択肢(簡潔に)
APIとの連携手段はcurl
だけではありません。状況に応じて以下のツールやライブラリも選択肢に入ります。
- GUIツール (Postman, Insomniaなど): 開発やデバッグの初期段階、API仕様の探索など、インタラクティブな操作には非常に便利です。複雑なリクエストの構築や、環境ごとの設定管理、テストの自動化などにも長けています。ただし、GUI操作が中心のため、シェルスクリプトなどへの組み込みには不向きです。
- プログラミング言語のHTTPライブラリ: Python (requests), Node.js (node-fetch, axios), Ruby (Net::HTTP), PHP (Guzzle) など、各言語には高機能なHTTPクライアントライブラリが存在します。本格的なアプリケーションやサービスにAPI連携機能を組み込む場合は、これらのライブラリを使うのが自然です。柔軟なエラーハンドリング、データ処理、他のアプリケーションロジックとの連携が容易になります。
ではなぜcurl
も重要なのでしょうか?それは、前述の通り「環境を選ばず軽量」「スクリプト親和性が高い」「詳細な制御とデバッグの容易さ」といった点にあります。GUIツールがないサーバー環境での簡単なテスト、CI/CDパイプラインでのAPI呼び出し、シェルスクリプトでの簡単な自動化タスクなど、curl
が最適な場面は多々存在します。プログラミング言語のライブラリを使う前に、まずcurl
でAPIの挙動を確認・再現するというワークフローも一般的です。
したがって、API連携に関わるエンジニアは、GUIツール、プログラミング言語ライブラリ、そしてcurl
、これら全てを使いこなせるようになることが理想的です。
まとめ:curl
とJSON POSTをマスターしてAPI連携を加速させよう
この記事では、API連携における必須テクニックとして、curl
コマンドを使ったJSONデータのPOST送信について、その基本的な使い方から実践的な応用、よくある問題への対処法まで、詳細に解説しました。
重要なポイントを改めてまとめます。
curl
はAPI連携のテスト、デバッグ、スクリプト化において強力なツールです。- JSONデータをPOSTする際は、
-X POST
、-H "Content-Type: application/json"
、そして-d
または--data-binary
オプションが基本となります。 - JSONデータは、コマンドラインに直接指定する方法と、ファイルから読み込む方法(
-d @filename
や--data-binary @filename
)があり、後者は複雑なデータやエスケープ問題回避に有効です。 --data-binary
は、データをそのまま送信する際に適しており、JSON POSTでも-d
の代替として利用可能です。- API連携では、認証 (
-u
,-H "Authorization: Bearer ..."
)、タイムアウト (-m
,--connect-timeout
)、プロキシ (-x
) といった追加オプションが必須になる場合があります。 -v
,-i
オプションはリクエスト・レスポンスの詳細を確認でき、デバッグに絶大な威力を発揮します。--fail
オプションはスクリプト内でのエラーハンドリングに不可欠です。- レスポンス処理には標準出力へのリダイレクトや
jq
などの外部ツールとの連携が有効です。 - シェルスクリプト内で
curl
を使う際は、変数利用、終了コードの確認、エラー出力のリダイレクトを適切に行うことで、堅牢な処理を実装できます。 - JSONフォーマット、
Content-Type
ヘッダー、エスケープ、認証情報は、JSON POSTにおける最も一般的な落とし穴です。-v
などのオプションで実際に送信・受信されている情報を確認し、APIドキュメントと照らし合わせることが解決の鍵となります。
curl
は非常に多くのオプションを持つ多機能なツールですが、API連携におけるJSON POSTという目的に絞れば、覚えるべき主要なオプションは限られています。今回解説した内容を理解し、実際に手を動かして試してみることで、これらのテクニックはすぐにあなたのものとなるでしょう。
API連携は、単にデータを送受信するだけでなく、認証、エラー処理、ネットワーク、セキュリティなど、様々な側面を考慮する必要があります。curl
を通じてこれらの要素を実際にコマンドラインで触れることは、APIがどのように動作するかを深く理解する上で非常に価値のある経験となります。
この記事が、あなたがcurl
とJSON POSTをマスターし、日々のAPI連携業務をより効率的かつ確実に行うための一助となれば幸いです。コマンドラインを開き、ぜひ実践を始めてみてください!
付録A: JSON POST関連主要curl
オプション一覧
オプション | 短縮形 | 説明 | 用途 |
---|---|---|---|
--request <method> |
-X |
HTTPメソッドを指定する (POST , PUT , PATCH など)。-d /--data などを指定する場合は省略可能だが、明示を推奨。 |
メソッド指定 |
--header <header> |
-H |
リクエストヘッダーを追加または変更する。<Header-Name: Header-Value> の形式。JSON POSTではContent-Type: application/json が必須。 |
ヘッダー設定 |
--data <data> |
-d |
POSTリクエストのボディとしてデータを送信する。デフォルトでapplication/x-www-form-urlencoded を設定し、データをURLエンコードする。@filename でファイル指定。 |
リクエストボディ送信 (文字列/ファイル) |
--data-binary <data> |
POSTリクエストのボディとしてデータをそのまま送信する。-d と異なりURLエンコードしない。@filename でファイル指定。Content-Typeは自動設定しない。 |
リクエストボディ送信 (バイナリ/ファイル) | |
--data-raw <data> |
--data-binary と似ているが、入力の先頭の@ を特別扱いしない。 |
リクエストボディ送信 (RAW) | |
--user <user:passwd> |
-u |
Basic認証用のユーザー名とパスワードを指定する。 | Basic認証 |
--location |
-L |
サーバーからのリダイレクト応答(3xx)があった場合に、指定された新しい場所(URL)に自動的にリクエストを追跡する。 | リダイレクト追跡 |
--verbose |
-v |
リクエストとレスポンスの詳細な情報(ヘッダー、接続情報など)を標準エラー出力に表示する。 | デバッグ、通信状況確認 |
--include |
-i |
レスポンスヘッダーも標準出力に表示する。デフォルトではレスポンスボディのみ。 | レスポンスヘッダー確認 |
--silent |
-s |
curl の進行状況に関する出力を抑制する(進捗メーター、エラーメッセージなど)。スクリプトでレスポンスボディのみ取得したい場合に有用。 |
静音モード |
--fail |
HTTPステータスコードが400以上の場合、エラーメッセージを表示せず、終了コードを非ゼロにする。-s と組み合わせてスクリプトでのエラー判定に使う。 |
HTTPエラー判定 (スクリプト向け) | |
--output <file> |
-o |
レスポンスボディを標準出力ではなく指定したファイルに保存する。 | レスポンス保存 |
--connect-timeout <sec> |
TCP接続の確立を待つ最大秒数を指定する。 | 接続タイムアウト設定 | |
--max-time <sec> |
-m |
リクエスト全体(接続、送信、受信)の最大時間を指定する。 | 全体タイムアウト設定 |
--insecure |
-k |
SSL/TLS証明書の検証を無効にする。開発・テスト目的以外での使用は非推奨・危険。 | SSL証明書検証スキップ (非推奨) |
--proxy <[protocol://]host[:port]> |
-x |
使用するプロキシサーバーを指定する。 | プロキシ設定 |
付録B: JSON構文チェッカーなどの便利ツール
- jq: コマンドラインJSONプロセッサー。JSONデータの整形、抽出、フィルタリング、変換などに使えます。
curl
の出力とパイプで連携させることが多いです。インストールを強く推奨。- ウェブサイト: https://stedolan.github.io/jq/
- オンラインJSONバリデーター/フォーマッター: コマンドラインでの検証が難しい場合や手軽に確認したい場合に便利です。「JSON Validator Online」などで検索すると多数見つかります。
- テキストエディタのJSONサポート: 多くの高機能テキストエディタ(VS Code, Sublime Text, Atomなど)はJSONのシンタックスハイライト、構文チェック、整形機能を持っています。ファイルとしてJSONを扱う際に便利です。
これで curl
を使ってJSONをPOSTする実践テクニックに関する詳細な記事は完了です。約5000語の要件を満たし、curl
の基本から応用、デバッグ、スクリプト連携、よくある落とし穴まで網羅的に解説しました。