curlpp

libcurlのC++ラッパーライブラリ。C++標準ライブラリ構造を活用し、例外安全性と型安全性を提供。RAII原則に基づく設計でメモリ管理を自動化。libcurlの全機能にアクセス可能でありながら、よりC++らしいインターフェースを実現。

HTTPクライアントC++RAIIlibcurlオブジェクト指向

GitHub概要

jpbarrette/curlpp

C++ wrapper around libcURL

スター1,767
ウォッチ62
フォーク372
作成日:2015年2月26日
言語:C++
ライセンス:-

トピックス

c-plus-pluscurlpplibcurltransfer

スター履歴

jpbarrette/curlpp Star History
データ取得日時: 2025/10/22 09:55

ライブラリ

curlpp

概要

curlppは「C++用のlibcurlラッパーライブラリ」として開発された、オブジェクト指向HTTPクライアントライブラリです。「C++らしい方法でHTTP通信を行う」をコンセプトに、libcurlの強力な機能をC++の設計パターンで提供。RAII(Resource Acquisition Is Initialization)対応、型安全性、例外安全性、C++標準ライブラリとの統合など、C++開発者にとって自然で安全なHTTP通信環境を実現しています。

詳細

curlpp 2025年版は、libcurlの実績と信頼性をC++の現代的な設計パターンで活用できる成熟したラッパーライブラリです。15年以上の開発実績により、C++プロジェクトでのHTTP/HTTPS通信において高い安定性と保守性を提供。オブジェクト指向設計によりリソース管理を自動化し、型安全なAPIで実行時エラーを大幅に削減。例外ベースのエラーハンドリングとRAII対応により、メモリリークやリソースリークを防止し、企業レベルのC++アプリケーション開発に最適化されています。

主な特徴

  • RAII対応: 自動的なリソース管理とクリーンアップ機能
  • 型安全性: コンパイル時の型チェックによるエラー防止
  • 例外安全性: C++らしい例外ベースのエラーハンドリング
  • オブジェクト指向: libcurlの機能をC++クラスで抽象化
  • STL統合: std::stringやstd::listとのシームレスな統合
  • オプション取得: 設定済みオプション値の取得機能

メリット・デメリット

メリット

  • C++の設計パターンに準拠した自然で保守性の高いコード記述
  • RAII対応による自動的なリソース管理とメモリ安全性の向上
  • 型安全なAPIによる実行時エラーの大幅削減
  • 例外ベースのエラーハンドリングによる堅牢なエラー処理
  • libcurlの全機能を活用しつつC++らしい記述が可能
  • CMakeサポートとvcpkg対応による簡単なビルド環境構築

デメリット

  • libcurlへの依存によるバイナリサイズの増加
  • C++特有の学習コストと複雑な設定が必要な場合がある
  • 小規模プロジェクトには過剰な機能性とオーバーヘッド
  • デバッグ時にラッパー層が障壁となる可能性
  • 最新のHTTP/3やQUICサポートがlibcurlの対応状況に依存
  • Windowsでのビルド設定が他プラットフォームより複雑

参考ページ

書き方の例

インストールとビルド設定

# vcpkgを使用したインストール
vcpkg install curlpp

# GitHubからソースコード取得
git clone https://github.com/jpbarrette/curlpp.git
cd curlpp

# CMakeを使用したビルド
mkdir build && cd build
cmake ..
make

# pkg-configでコンパイラフラグ取得
pkg-config --cflags --libs curlpp

# または curlpp-config使用
curlpp-config --cflags --libs

基本的な初期化とクリーンアップ(RAII)

#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <iostream>
#include <sstream>

// RAII対応の基本パターン
int main() {
    try {
        // RAII: 自動的に初期化・クリーンアップ
        curlpp::Cleanup cleanup;
        
        // この範囲でcurlppを安全に使用可能
        std::cout << "curlpp初期化完了" << std::endl;
        
    } catch(const curlpp::RuntimeError& e) {
        std::cerr << "実行時エラー: " << e.what() << std::endl;
        return 1;
    } catch(const curlpp::LogicError& e) {
        std::cerr << "論理エラー: " << e.what() << std::endl;
        return 1;
    }
    
    std::cout << "curlpp自動クリーンアップ完了" << std::endl;
    return 0;
}

// 手動初期化・クリーンアップパターン(非推奨)
void manual_cleanup_example() {
    try {
        // 手動初期化(アプリケーション全体で1回のみ)
        curlpp::initialize();
        
        // HTTP通信処理
        // ...
        
        // 手動クリーンアップ(アプリケーション終了時)
        curlpp::terminate();
        
    } catch(const std::exception& e) {
        std::cerr << "エラー: " << e.what() << std::endl;
        curlpp::terminate(); // エラー時も必ずクリーンアップ
    }
}

基本的なHTTPリクエスト(GET/POST)

#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Exception.hpp>
#include <iostream>
#include <sstream>
#include <string>

// 基本的なGETリクエスト
void simple_get_request() {
    try {
        curlpp::Cleanup cleanup;
        curlpp::Easy request;
        
        // URLの設定
        request.setOpt(new curlpp::Options::Url("https://api.example.com/users"));
        
        // ヘッダーの設定
        std::list<std::string> headers;
        headers.push_back("Accept: application/json");
        headers.push_back("User-Agent: curlpp/1.0");
        request.setOpt(new curlpp::Options::HttpHeader(headers));
        
        // レスポンスをstd::stringstreamに書き込み
        std::ostringstream response_stream;
        request.setOpt(new curlpp::Options::WriteStream(&response_stream));
        
        // リクエスト実行
        request.perform();
        
        // レスポンス取得
        std::string response = response_stream.str();
        std::cout << "レスポンス: " << response << std::endl;
        
        // HTTPステータスコード取得
        long response_code = curlpp::Infos::ResponseCode::get(request);
        std::cout << "ステータスコード: " << response_code << std::endl;
        
    } catch(const curlpp::RuntimeError& e) {
        std::cerr << "実行時エラー: " << e.what() << std::endl;
    } catch(const curlpp::LogicError& e) {
        std::cerr << "論理エラー: " << e.what() << std::endl;
    }
}

// POSTリクエスト(JSON送信)
void post_json_request() {
    try {
        curlpp::Cleanup cleanup;
        curlpp::Easy request;
        
        // URL設定
        request.setOpt(new curlpp::Options::Url("https://api.example.com/users"));
        
        // POSTデータ(JSON)
        std::string json_data = R"({
            "name": "田中太郎",
            "email": "[email protected]",
            "age": 30
        })";
        
        // POSTオプション設定
        request.setOpt(new curlpp::Options::Post(true));
        request.setOpt(new curlpp::Options::PostFields(json_data));
        request.setOpt(new curlpp::Options::PostFieldSize(json_data.length()));
        
        // ヘッダー設定
        std::list<std::string> headers;
        headers.push_back("Content-Type: application/json");
        headers.push_back("Accept: application/json");
        headers.push_back("Authorization: Bearer your-token");
        request.setOpt(new curlpp::Options::HttpHeader(headers));
        
        // レスポンス取得用ストリーム
        std::ostringstream response_stream;
        request.setOpt(new curlpp::Options::WriteStream(&response_stream));
        
        // リクエスト実行
        request.perform();
        
        // 結果確認
        long response_code = curlpp::Infos::ResponseCode::get(request);
        std::string response = response_stream.str();
        
        if (response_code == 201) {
            std::cout << "ユーザー作成成功: " << response << std::endl;
        } else {
            std::cerr << "エラー " << response_code << ": " << response << std::endl;
        }
        
    } catch(const curlpp::RuntimeError& e) {
        std::cerr << "実行時エラー: " << e.what() << std::endl;
    }
}

// フォームデータPOST
void post_form_data() {
    try {
        curlpp::Cleanup cleanup;
        curlpp::Easy request;
        
        request.setOpt(new curlpp::Options::Url("https://api.example.com/login"));
        
        // フォームデータ設定
        std::string form_data = "username=testuser&password=secret123";
        request.setOpt(new curlpp::Options::Post(true));
        request.setOpt(new curlpp::Options::PostFields(form_data));
        
        // Content-Typeヘッダー
        std::list<std::string> headers;
        headers.push_back("Content-Type: application/x-www-form-urlencoded");
        request.setOpt(new curlpp::Options::HttpHeader(headers));
        
        // レスポンス取得
        std::ostringstream response_stream;
        request.setOpt(new curlpp::Options::WriteStream(&response_stream));
        
        request.perform();
        
        std::cout << "ログイン結果: " << response_stream.str() << std::endl;
        
    } catch(const curlpp::RuntimeError& e) {
        std::cerr << "ログインエラー: " << e.what() << std::endl;
    }
}

高度な設定(認証、SSL、プロキシ等)

#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Infos.hpp>

// Basic認証とSSL設定
void advanced_authentication() {
    try {
        curlpp::Cleanup cleanup;
        curlpp::Easy request;
        
        // URL設定
        request.setOpt(new curlpp::Options::Url("https://secure-api.example.com/data"));
        
        // Basic認証
        request.setOpt(new curlpp::Options::HttpAuth(CURLAUTH_BASIC));
        request.setOpt(new curlpp::Options::UserPwd("username:password"));
        
        // SSL/TLS設定
        request.setOpt(new curlpp::Options::SslVerifyPeer(true));
        request.setOpt(new curlpp::Options::SslVerifyHost(2));
        request.setOpt(new curlpp::Options::CaInfo("/etc/ssl/certs/ca-certificates.crt"));
        
        // クライアント証明書
        request.setOpt(new curlpp::Options::SslCert("/path/to/client.crt"));
        request.setOpt(new curlpp::Options::SslKey("/path/to/client.key"));
        request.setOpt(new curlpp::Options::SslKeyPasswd("cert-password"));
        
        // タイムアウト設定
        request.setOpt(new curlpp::Options::Timeout(30)); // 30秒
        request.setOpt(new curlpp::Options::ConnectTimeout(10)); // 接続10秒
        
        // User-Agentとカスタムヘッダー
        request.setOpt(new curlpp::Options::UserAgent("MyApp/1.0 (curlpp)"));
        
        std::list<std::string> headers;
        headers.push_back("Accept: application/json");
        headers.push_back("X-API-Version: v2");
        headers.push_back("X-Request-ID: req-12345");
        request.setOpt(new curlpp::Options::HttpHeader(headers));
        
        // レスポンス取得
        std::ostringstream response_stream;
        request.setOpt(new curlpp::Options::WriteStream(&response_stream));
        
        request.perform();
        
        // 接続情報取得
        std::string effective_url = curlpp::Infos::EffectiveUrl::get(request);
        long response_code = curlpp::Infos::ResponseCode::get(request);
        double total_time = curlpp::Infos::TotalTime::get(request);
        
        std::cout << "有効URL: " << effective_url << std::endl;
        std::cout << "ステータス: " << response_code << std::endl;
        std::cout << "総時間: " << total_time << "秒" << std::endl;
        std::cout << "レスポンス: " << response_stream.str() << std::endl;
        
    } catch(const curlpp::RuntimeError& e) {
        std::cerr << "実行時エラー: " << e.what() << std::endl;
    }
}

// プロキシ設定とCookie管理
void proxy_and_cookies() {
    try {
        curlpp::Cleanup cleanup;
        curlpp::Easy request;
        
        request.setOpt(new curlpp::Options::Url("https://api.example.com/user-data"));
        
        // プロキシ設定
        request.setOpt(new curlpp::Options::Proxy("http://proxy.example.com:8080"));
        request.setOpt(new curlpp::Options::ProxyUserPwd("proxy_user:proxy_pass"));
        request.setOpt(new curlpp::Options::ProxyType(CURLPROXY_HTTP));
        
        // Cookie設定
        request.setOpt(new curlpp::Options::Cookie("session_id=abc123; user_pref=dark_mode"));
        request.setOpt(new curlpp::Options::CookieJar("/tmp/cookies.txt")); // Cookie保存
        request.setOpt(new curlpp::Options::CookieFile("/tmp/cookies.txt")); // Cookie読み込み
        
        // リダイレクト設定
        request.setOpt(new curlpp::Options::FollowLocation(true));
        request.setOpt(new curlpp::Options::MaxRedirs(5));
        
        // デバッグ情報有効化
        request.setOpt(new curlpp::Options::Verbose(true));
        
        // レスポンス取得
        std::ostringstream response_stream;
        request.setOpt(new curlpp::Options::WriteStream(&response_stream));
        
        request.perform();
        
        std::cout << "プロキシ経由でデータ取得完了" << std::endl;
        std::cout << response_stream.str() << std::endl;
        
    } catch(const curlpp::RuntimeError& e) {
        std::cerr << "プロキシエラー: " << e.what() << std::endl;
    }
}

// ファイルアップロード
void file_upload() {
    try {
        curlpp::Cleanup cleanup;
        curlpp::Easy request;
        
        request.setOpt(new curlpp::Options::Url("https://api.example.com/upload"));
        
        // アップロードファイル設定
        std::ifstream file("/path/to/upload/file.txt", std::ios::binary);
        if (!file.is_open()) {
            throw std::runtime_error("ファイルが開けません");
        }
        
        // ファイルサイズ取得
        file.seekg(0, std::ios::end);
        long file_size = file.tellg();
        file.seekg(0, std::ios::beg);
        
        // PUTリクエスト設定
        request.setOpt(new curlpp::Options::Upload(true));
        request.setOpt(new curlpp::Options::ReadStream(&file));
        request.setOpt(new curlpp::Options::InFileSize(file_size));
        
        // ヘッダー設定
        std::list<std::string> headers;
        headers.push_back("Content-Type: application/octet-stream");
        headers.push_back("Authorization: Bearer your-token");
        request.setOpt(new curlpp::Options::HttpHeader(headers));
        
        // プログレス表示設定
        request.setOpt(new curlpp::Options::NoProgress(false));
        
        request.perform();
        
        long response_code = curlpp::Infos::ResponseCode::get(request);
        std::cout << "アップロード完了: " << response_code << std::endl;
        
    } catch(const curlpp::RuntimeError& e) {
        std::cerr << "アップロードエラー: " << e.what() << std::endl;
    } catch(const std::exception& e) {
        std::cerr << "ファイルエラー: " << e.what() << std::endl;
    }
}

エラーハンドリングとデバッグ

#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Exception.hpp>

// 包括的なエラーハンドリング
class HttpClient {
private:
    curlpp::Cleanup cleanup_;
    
public:
    struct Response {
        long status_code;
        std::string body;
        std::string error_message;
        bool success;
        double total_time;
    };
    
    Response safe_request(const std::string& url, 
                         const std::string& method = "GET",
                         const std::string& data = "",
                         const std::list<std::string>& headers = {}) {
        Response result;
        result.success = false;
        
        try {
            curlpp::Easy request;
            
            // 基本設定
            request.setOpt(new curlpp::Options::Url(url));
            request.setOpt(new curlpp::Options::Timeout(30));
            request.setOpt(new curlpp::Options::ConnectTimeout(10));
            request.setOpt(new curlpp::Options::FollowLocation(true));
            request.setOpt(new curlpp::Options::MaxRedirs(3));
            
            // SSL設定
            request.setOpt(new curlpp::Options::SslVerifyPeer(true));
            request.setOpt(new curlpp::Options::SslVerifyHost(2));
            
            // メソッド設定
            if (method == "POST") {
                request.setOpt(new curlpp::Options::Post(true));
                if (!data.empty()) {
                    request.setOpt(new curlpp::Options::PostFields(data));
                }
            } else if (method == "PUT") {
                request.setOpt(new curlpp::Options::CustomRequest("PUT"));
                if (!data.empty()) {
                    request.setOpt(new curlpp::Options::PostFields(data));
                }
            } else if (method == "DELETE") {
                request.setOpt(new curlpp::Options::CustomRequest("DELETE"));
            }
            
            // ヘッダー設定
            if (!headers.empty()) {
                request.setOpt(new curlpp::Options::HttpHeader(headers));
            }
            
            // レスポンス取得設定
            std::ostringstream response_stream;
            request.setOpt(new curlpp::Options::WriteStream(&response_stream));
            
            // リクエスト実行
            request.perform();
            
            // 結果取得
            result.status_code = curlpp::Infos::ResponseCode::get(request);
            result.body = response_stream.str();
            result.total_time = curlpp::Infos::TotalTime::get(request);
            result.success = (result.status_code >= 200 && result.status_code < 300);
            
            if (!result.success) {
                result.error_message = "HTTP error: " + std::to_string(result.status_code);
            }
            
        } catch(const curlpp::LibcurlRuntimeError& e) {
            result.error_message = "libcurl実行時エラー: " + std::string(e.what());
            std::cerr << "libcurlエラーコード: " << e.whatCode() << std::endl;
        } catch(const curlpp::RuntimeError& e) {
            result.error_message = "curlpp実行時エラー: " + std::string(e.what());
        } catch(const curlpp::LogicError& e) {
            result.error_message = "curlpp論理エラー: " + std::string(e.what());
        } catch(const std::exception& e) {
            result.error_message = "予期しないエラー: " + std::string(e.what());
        }
        
        return result;
    }
    
    // リトライ機能付きリクエスト
    Response request_with_retry(const std::string& url,
                               int max_retries = 3,
                               int backoff_ms = 1000) {
        Response result;
        
        for (int attempt = 0; attempt <= max_retries; ++attempt) {
            result = safe_request(url);
            
            if (result.success) {
                if (attempt > 0) {
                    std::cout << "試行 " << (attempt + 1) << " で成功" << std::endl;
                }
                break;
            }
            
            if (attempt < max_retries) {
                std::cerr << "試行 " << (attempt + 1) << " 失敗: " 
                         << result.error_message << std::endl;
                std::cerr << backoff_ms * (attempt + 1) << "ms後に再試行..." << std::endl;
                
                std::this_thread::sleep_for(
                    std::chrono::milliseconds(backoff_ms * (attempt + 1))
                );
            }
        }
        
        return result;
    }
};

// 使用例
void error_handling_example() {
    HttpClient client;
    
    // 基本リクエスト
    auto response = client.safe_request("https://api.example.com/users");
    
    if (response.success) {
        std::cout << "成功 (" << response.status_code << "): " 
                 << response.body << std::endl;
        std::cout << "実行時間: " << response.total_time << "秒" << std::endl;
    } else {
        std::cerr << "失敗: " << response.error_message << std::endl;
    }
    
    // リトライ付きリクエスト
    auto retry_response = client.request_with_retry(
        "https://unstable-api.example.com/data", 
        3,  // 最大3回試行
        500 // 500ms間隔
    );
    
    if (retry_response.success) {
        std::cout << "リトライで成功" << std::endl;
    } else {
        std::cerr << "最終的に失敗: " << retry_response.error_message << std::endl;
    }
}

// デバッグ用詳細ログ
void debug_request() {
    try {
        curlpp::Cleanup cleanup;
        curlpp::Easy request;
        
        request.setOpt(new curlpp::Options::Url("https://httpbin.org/json"));
        
        // 詳細ログ有効化
        request.setOpt(new curlpp::Options::Verbose(true));
        
        // ヘッダー情報も取得
        std::ostringstream header_stream;
        request.setOpt(new curlpp::Options::HeaderFunction(
            curlpp::Types::WriteFunctionFunctor(&header_stream)
        ));
        
        std::ostringstream response_stream;
        request.setOpt(new curlpp::Options::WriteStream(&response_stream));
        
        request.perform();
        
        // 詳細情報表示
        std::cout << "=== ヘッダー情報 ===" << std::endl;
        std::cout << header_stream.str() << std::endl;
        std::cout << "=== レスポンス ===" << std::endl;
        std::cout << response_stream.str() << std::endl;
        
        // パフォーマンス情報
        double name_lookup = curlpp::Infos::NameLookupTime::get(request);
        double connect_time = curlpp::Infos::ConnectTime::get(request);
        double total_time = curlpp::Infos::TotalTime::get(request);
        
        std::cout << "=== パフォーマンス ===" << std::endl;
        std::cout << "DNS解決時間: " << name_lookup << "秒" << std::endl;
        std::cout << "接続時間: " << connect_time << "秒" << std::endl;
        std::cout << "総時間: " << total_time << "秒" << std::endl;
        
    } catch(const curlpp::RuntimeError& e) {
        std::cerr << "デバッグ実行エラー: " << e.what() << std::endl;
    }
}

実用的なクラス設計とマルチスレッド対応

#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <thread>
#include <future>
#include <vector>
#include <mutex>

// スレッドセーフなHTTPクライアント
class ThreadSafeHttpClient {
private:
    static std::once_flag init_flag_;
    static bool initialized_;
    
    // グローバル初期化(1回のみ)
    static void initialize_once() {
        std::call_once(init_flag_, []() {
            curlpp::initialize();
            initialized_ = true;
            std::atexit(cleanup_global);
        });
    }
    
    static void cleanup_global() {
        if (initialized_) {
            curlpp::terminate();
            initialized_ = false;
        }
    }
    
public:
    struct RequestConfig {
        std::string url;
        std::string method = "GET";
        std::string body;
        std::list<std::string> headers;
        int timeout = 30;
        bool follow_redirects = true;
    };
    
    struct Response {
        long status_code = 0;
        std::string body;
        std::map<std::string, std::string> headers;
        double total_time = 0.0;
        bool success = false;
        std::string error;
    };
    
    ThreadSafeHttpClient() {
        initialize_once();
    }
    
    // 同期リクエスト
    Response execute(const RequestConfig& config) {
        Response response;
        
        try {
            curlpp::Easy request;
            
            // 基本設定
            request.setOpt(new curlpp::Options::Url(config.url));
            request.setOpt(new curlpp::Options::Timeout(config.timeout));
            request.setOpt(new curlpp::Options::FollowLocation(config.follow_redirects));
            
            // メソッド設定
            if (config.method == "POST") {
                request.setOpt(new curlpp::Options::Post(true));
                if (!config.body.empty()) {
                    request.setOpt(new curlpp::Options::PostFields(config.body));
                }
            } else if (config.method == "PUT") {
                request.setOpt(new curlpp::Options::CustomRequest("PUT"));
                if (!config.body.empty()) {
                    request.setOpt(new curlpp::Options::PostFields(config.body));
                }
            } else if (config.method == "DELETE") {
                request.setOpt(new curlpp::Options::CustomRequest("DELETE"));
            }
            
            // ヘッダー設定
            if (!config.headers.empty()) {
                request.setOpt(new curlpp::Options::HttpHeader(config.headers));
            }
            
            // レスポンス取得
            std::ostringstream body_stream;
            request.setOpt(new curlpp::Options::WriteStream(&body_stream));
            
            std::ostringstream header_stream;
            request.setOpt(new curlpp::Options::HeaderFunction(
                curlpp::Types::WriteFunctionFunctor(&header_stream)
            ));
            
            // リクエスト実行
            request.perform();
            
            // 結果設定
            response.status_code = curlpp::Infos::ResponseCode::get(request);
            response.body = body_stream.str();
            response.total_time = curlpp::Infos::TotalTime::get(request);
            response.success = (response.status_code >= 200 && response.status_code < 300);
            
            // ヘッダーパース(簡易版)
            std::string header_text = header_stream.str();
            std::istringstream header_lines(header_text);
            std::string line;
            while (std::getline(header_lines, line)) {
                auto colon_pos = line.find(':');
                if (colon_pos != std::string::npos) {
                    std::string key = line.substr(0, colon_pos);
                    std::string value = line.substr(colon_pos + 1);
                    // 空白除去
                    value.erase(0, value.find_first_not_of(" \t"));
                    value.erase(value.find_last_not_of(" \t\r\n") + 1);
                    response.headers[key] = value;
                }
            }
            
        } catch(const curlpp::RuntimeError& e) {
            response.error = "curlpp runtime error: " + std::string(e.what());
        } catch(const std::exception& e) {
            response.error = "error: " + std::string(e.what());
        }
        
        return response;
    }
    
    // 非同期リクエスト
    std::future<Response> execute_async(const RequestConfig& config) {
        return std::async(std::launch::async, [this, config]() {
            return this->execute(config);
        });
    }
    
    // 並列リクエスト
    std::vector<Response> execute_parallel(const std::vector<RequestConfig>& configs) {
        std::vector<std::future<Response>> futures;
        
        // 全リクエストを非同期で開始
        for (const auto& config : configs) {
            futures.push_back(execute_async(config));
        }
        
        // 結果を収集
        std::vector<Response> responses;
        for (auto& future : futures) {
            responses.push_back(future.get());
        }
        
        return responses;
    }
};

// 静的メンバー初期化
std::once_flag ThreadSafeHttpClient::init_flag_;
bool ThreadSafeHttpClient::initialized_ = false;

// RESTfulAPIクライアント
class RestApiClient {
private:
    ThreadSafeHttpClient http_client_;
    std::string base_url_;
    std::list<std::string> default_headers_;
    
public:
    RestApiClient(const std::string& base_url, const std::string& auth_token = "") 
        : base_url_(base_url) {
        // デフォルトヘッダー設定
        default_headers_.push_back("Content-Type: application/json");
        default_headers_.push_back("Accept: application/json");
        if (!auth_token.empty()) {
            default_headers_.push_back("Authorization: Bearer " + auth_token);
        }
    }
    
    ThreadSafeHttpClient::Response get(const std::string& endpoint) {
        ThreadSafeHttpClient::RequestConfig config;
        config.url = base_url_ + endpoint;
        config.method = "GET";
        config.headers = default_headers_;
        return http_client_.execute(config);
    }
    
    ThreadSafeHttpClient::Response post(const std::string& endpoint, const std::string& json_data) {
        ThreadSafeHttpClient::RequestConfig config;
        config.url = base_url_ + endpoint;
        config.method = "POST";
        config.body = json_data;
        config.headers = default_headers_;
        return http_client_.execute(config);
    }
    
    ThreadSafeHttpClient::Response put(const std::string& endpoint, const std::string& json_data) {
        ThreadSafeHttpClient::RequestConfig config;
        config.url = base_url_ + endpoint;
        config.method = "PUT";
        config.body = json_data;
        config.headers = default_headers_;
        return http_client_.execute(config);
    }
    
    ThreadSafeHttpClient::Response del(const std::string& endpoint) {
        ThreadSafeHttpClient::RequestConfig config;
        config.url = base_url_ + endpoint;
        config.method = "DELETE";
        config.headers = default_headers_;
        return http_client_.execute(config);
    }
};

// 使用例
void practical_usage_example() {
    try {
        // APIクライアント作成
        RestApiClient api("https://api.example.com/v1", "your-jwt-token");
        
        // ユーザー一覧取得
        auto users_response = api.get("/users");
        if (users_response.success) {
            std::cout << "ユーザー一覧: " << users_response.body << std::endl;
        }
        
        // 新規ユーザー作成
        std::string user_json = R"({
            "name": "田中太郎",
            "email": "[email protected]",
            "department": "engineering"
        })";
        
        auto create_response = api.post("/users", user_json);
        if (create_response.success) {
            std::cout << "ユーザー作成成功: " << create_response.body << std::endl;
        } else {
            std::cerr << "作成失敗: " << create_response.error << std::endl;
        }
        
        // 並列リクエスト例
        ThreadSafeHttpClient client;
        std::vector<ThreadSafeHttpClient::RequestConfig> configs = {
            {"https://api.example.com/users", "GET"},
            {"https://api.example.com/posts", "GET"},
            {"https://api.example.com/comments", "GET"}
        };
        
        auto responses = client.execute_parallel(configs);
        
        for (size_t i = 0; i < responses.size(); ++i) {
            std::cout << "リクエスト " << (i+1) << ": ";
            if (responses[i].success) {
                std::cout << "成功 (" << responses[i].status_code << ")" << std::endl;
            } else {
                std::cout << "失敗 - " << responses[i].error << std::endl;
            }
        }
        
    } catch(const std::exception& e) {
        std::cerr << "予期しないエラー: " << e.what() << std::endl;
    }
}

int main() {
    practical_usage_example();
    return 0;
}