curlでHTTP/2とJSONを操る

ネットワーク・RFCカテゴリを表すパンダのイラスト ネットワーク・RFC

本記事は、curl コマンドを使用してHTTP/2通信やJSONデータを安全に扱うための実践的な手順を解説します。

curlでHTTP/2とJSONを操る

要件と前提

本記事は、DevOpsエンジニアが curl コマンドを使用してHTTP/2プロトコル経由でJSON形式のAPIと安全かつ効率的に連携するための実践的な手法を解説します。特に、安全なbashスクリプティング、jq を用いたJSON処理、systemd を利用したジョブ自動化に焦点を当てます。

前提ツール:

  • curl (HTTP/2サポート版)

  • jq

  • bash (バージョン4.x以上推奨)

  • systemd (Linux環境)

注意事項:

  • 本記事のスクリプトはLinux環境を想定しています。

  • systemd サービスの設定には通常 root 権限が必要ですが、実行ユーザーは可能な限り非特権ユーザーを指定し、権限分離を徹底してください。

実装

まず、安全で冪等な(idempotent)処理を実現するためのbashスクリプトのひな形と、curl および jq を組み合わせた具体的なAPI連携スクリプトを実装します。

安全なbashスクリプトのフレームワーク

#!/usr/bin/env bash

# set -euo pipefail:
# -e: コマンドが失敗した場合、即座にスクリプトを終了
# -u: 未定義の変数が使用された場合、エラーで終了
# -o pipefail: パイプライン内で一つでも失敗したコマンドがあれば、パイプライン全体を失敗とする

set -euo pipefail

# 一時ディレクトリの作成と自動削除
# mktemp -d: 一意な名前の一時ディレクトリを作成
# trap '...' EXIT: スクリプト終了時に指定したコマンドを実行 (正常終了/異常終了問わず)

TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"; echo "Temporary directory $TMP_DIR removed."' EXIT

echo "Starting API interaction script."
echo "Temporary directory: $TMP_DIR"

# APIエンドポイントの定義 (例としてhttpbin.orgを使用)
API_URL="https://httpbin.org/anything"

# --- ここから具体的なAPI連携処理 ---

# 1. 送信するJSONペイロードの作成
PAYLOAD_FILE="$TMP_DIR/payload.json"
cat << 'EOF' > "$PAYLOAD_FILE"
{
  "service_name": "example-service",
  "status": "active",
  "timestamp": "$(date -uIs)",
  "metadata": {
    "version": "1.0.0",
    "region": "us-east-1"
  }
}
EOF
# プレースホルダーを展開するために日付部分を動的に設定
cat << EOF > "$PAYLOAD_FILE"
{
  "service_name": "example-service",
  "status": "active",
  "timestamp": "$(date -uIs)",
  "metadata": {
    "version": "1.0.0",
    "region": "us-east-1"
  }
}
EOF

echo "Generated payload.json:"
cat "$PAYLOAD_FILE" | jq '.'

# 2. curlでのHTTP/2リクエスト送信とJSONレスポンスの受信
echo "Sending HTTP/2 POST request to $API_URL..."
API_RESPONSE=$(curl --http2 -sS \
  --retry 5 --retry-delay 2 --retry-max-time 30 \
  --connect-timeout 5 --max-time 10 \
  -X POST \
  -H "Content-Type: application/json" \
  --data "@$PAYLOAD_FILE" \
  "$API_URL")

# エラーハンドリング: curlコマンドが失敗した場合
if [ $? -ne 0 ]; then
    echo "ERROR: curl command failed." >&2
    exit 1
fi

echo "API Response received."

# 3. jqを用いたJSONレスポンスの処理
if echo "$API_RESPONSE" | jq -e . >/dev/null; then
    echo "Processed JSON response with jq:"
    echo "$API_RESPONSE" | jq -r '
        .json.service_name as $service_name |
        .json.status as $status |
        .url as $url |
        "Service: \($service_name), Status: \($status), URL: \($url)"
    '

    if echo "$API_RESPONSE" | jq -e '.json.status == "active"' >/dev/null; then
        echo "Service is active, proceeding with next step..."
    else
        echo "Service status is not 'active'."
    fi
else
    echo "ERROR: API response is not valid JSON or jq processing failed." >&2
    echo "Raw response: $API_RESPONSE" >&2
    exit 1
fi

echo "Script finished successfully."

Mermaid図

API連携のフローを簡潔に示します。

graph TD
    A["Start Script"] --> B{"Setup: Temp Dir & Trap"};
    B -->|"Prepare Request Data"| C["Create JSON Payload"]
    C -->|"Send via curl"| D{"API Endpoint (HTTP/2, Retry)"}
    D -->|"Receive JSON Response"| E["Process Response with jq"]
    E -->|"Log & Act on Data"| F["Handle Business Logic"]
    F -->|"Cleanup"| G{"Remove Temp Dir"}
    G --> H["End Script"];

検証

上記のスクリプトを my_api_job.sh として保存し、実行して動作を確認します。

# スクリプトを実行可能にする
chmod +x my_api_job.sh

# 実行
./my_api_job.sh

期待される出力:

  • 一時ディレクトリの作成と削除メッセージ。

  • 生成された payload.json の内容。

  • curl によるリクエスト送信メッセージ。

  • APIからのレスポンスを jq で整形した結果。

  • サービスが “active” である場合の追加メッセージ。

curl -v --http2 <URL> を実行することで、HTTP/2が利用されているかを確認できます。出力中に ALPN, offering h2 や ALPN, negotiated h2 といった行があれば、HTTP/2が使用されています。

運用

定期的なAPI呼び出しやバックグラウンド処理には、systemd unit/timer を用いるのがDevOpsのベストプラクティスです。

systemd Unitファイルの作成

/etc/systemd/system/my-api-job.service を作成します。

[Unit]
Description=My API Interaction Job
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
WorkingDirectory=/usr/local/bin
ExecStart=/usr/local/bin/my_api_job.sh
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

root権限と権限分離の注意点: systemd サービスは通常 root ユーザーによって管理されますが、ExecStart で実行されるプロセス自体は可能な限り非特権ユーザーで実行すべきです。これにより、スクリプトに潜在的な脆弱性があった場合でも、システム全体への影響を最小限に抑えることができます。

systemd Timerファイルの作成

/etc/systemd/system/my-api-job.timer を作成します。

[Unit]
Description=Run My API Interaction Job Daily

[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true

[Install]
WantedBy=timers.target

インストールと有効化

  1. 上記スクリプトを /usr/local/bin/my_api_job.sh に配置し、実行権限を与えます。

    sudo mv my_api_job.sh /usr/local/bin/
    sudo chmod +x /usr/local/bin/my_api_job.sh
    
  2. systemd 設定ファイルをリロードします。

    sudo systemctl daemon-reload
    
  3. タイマーを有効化し、起動します。

    sudo systemctl enable my-api-job.timer
    sudo systemctl start my-api-job.timer
    

ログの確認

サービスが実行された後のログは journalctl で確認できます。

journalctl -u my-api-job.service
journalctl -u my-api-job.service -n 20

トラブルシュート

  • curl がエラーになる場合:

    • --verbose オプションを追加し、詳細な通信ログを確認します。

    • TLS証明書のエラーの場合は --cacert 等を確認してください。

  • jq がJSONをパースできない場合:

    • サーバーから予期せぬ出力(HTML等)が返されていないか確認します。

まとめ

本記事では、DevOpsエンジニアが curl を用いてHTTP/2とJSON形式のAPIを操作するための包括的なアプローチを解説しました。安全なbashスクリプトのベストプラクティス、jq による強力なJSON処理、そして systemd unit/timer による堅牢な自動化と運用方法を組み合わせることで、API連携処理を効率的かつセキュアに管理できます。

この記事の更新履歴

この記事は、生成AIを活用した自動レビュー・更新フローにより内容を見直し、必要な修正を反映しています。

2026年9月14日

  • 変更導入部の冒頭にあった未検証ドラフトの注意書き文言と体裁を正式な記事向けに調整しました。
  • 変更まとめの冒頭にあった句読点の脱落や不自然な文言を修正しました。

文書情報

記事タイトル
curlでHTTP/2とJSONを操る
作成日
更新日
Source URL
https://papanda925.com/?p=3467

ライセンス: 本記事のうち、当サイトが権利を有する本文・自作図表は、特記なき限り CC BY 4.0 で利用できます。生成AIを活用して作成・編集した内容を含みます。コードについて、別途ライセンス表示またはリンク先GitHubリポジトリのライセンスがある場合は、その条件を優先します。引用・第三者資料・画像・商標等は本ライセンスの対象外です。 利用ポリシー

タイトルとURLをコピーしました