cpp-httplib

C++11対応のヘッダーオンリーHTTPクライアント・サーバーライブラリ。単一ヘッダーファイルで簡単に統合可能。HTTP/HTTPS対応、SSL/TLS、マルチパート、レンジリクエスト、基本認証、JSON処理機能をコンパクトに提供。

HTTPクライアントC++ヘッダーオンリーサーバークライアントSSL/TLS

GitHub概要

yhirose/cpp-httplib

A C++ header-only HTTP/HTTPS server and client library

スター15,091
ウォッチ189
フォーク2,519
作成日:2012年9月22日
言語:C++
ライセンス:MIT License

トピックス

cppcpp11header-onlyhttphttps

スター履歴

yhirose/cpp-httplib Star History
データ取得日時: 2025/10/22 09:55

ライブラリ

cpp-httplib

概要

cpp-httplibは「C++11準拠のシングルファイル・ヘッダーオンリーHTTP/HTTPSライブラリ」として開発された、最も統合しやすいC++ HTTPライブラリの一つです。「シンプルで使いやすい」をコンセプトに、わずか1つのヘッダーファイル(httplib.h)を含むだけでHTTPサーバーとクライアント機能を提供。ブロッキングソケットI/Oによる直感的なプログラミングモデル、マルチプラットフォーム対応、SSL/TLS暗号化サポートなど、C++アプリケーションでのHTTP通信に必要な機能を包括的に提供し、軽量性と使いやすさを重視する開発者にとって理想的な選択肢となっています。

詳細

cpp-httplib 2025年版は、C++11以降の環境で最高の統合体験を提供する成熟したHTTPライブラリとして確固たる地位を確立しています。15年以上の開発実績により洗練されたAPIと高い安定性を誇り、Windows、Linux、macOS環境で幅広く採用されています。シングルヘッダー設計により外部依存関係を最小化し、プロジェクトへの統合が極めて簡単。ブロッキングI/Oによるシンプルなプログラミングモデルで、HTTPサーバー・クライアント双方の機能を直感的に実装可能。OpenSSLサポートによるHTTPS対応、マルチパート・フォームデータ処理、認証システム、プロキシサポートなど企業レベルのHTTP通信要件を満たします。

主な特徴

  • ヘッダーオンリー設計: httplib.hファイル1つだけで完全機能
  • サーバー・クライアント統合: 単一ライブラリで双方向HTTP通信
  • C++11準拠: モダンC++標準に完全対応
  • マルチプラットフォーム: Windows、Linux、macOS完全サポート
  • SSL/TLS暗号化: OpenSSL 3.0+による完全HTTPS対応
  • ブロッキングI/O: 理解しやすい同期プログラミングモデル

メリット・デメリット

メリット

  • 極めて簡単な統合プロセスと最小限の依存関係管理
  • シングルヘッダー設計による配布・デプロイの簡素化
  • 直感的なAPIによる高い学習効率とコード可読性
  • サーバー・クライアント双方の機能を統一ライブラリで提供
  • ブロッキングI/Oモデルによる予測可能な実行フロー
  • 豊富なHTTP機能サポート(認証、プロキシ、マルチパート等)

デメリット

  • ブロッキングI/Oによる同時接続数の制約(高スループット不向き)
  • スレッドプール依存による大量並行処理でのリソース消費
  • 非同期I/Oライブラリと比較した場合のパフォーマンス劣位
  • OpenSSL依存によるHTTPS利用時の外部ライブラリ要求
  • I/O集約的なアプリケーションでのスケーラビリティ制限
  • 最高性能が要求される用途での機能・性能トレードオフ

参考ページ

書き方の例

インストールと基本セットアップ

// cpp-httplibの使用(ヘッダーオンリー)
#include "httplib.h"

// HTTPS利用時のOpenSSLサポート有効化
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include "httplib.h"

// コンパイル例(Linux/macOS)
// g++ -std=c++11 your_app.cpp -pthread

// HTTPS使用時のリンクオプション
// g++ -std=c++11 your_app.cpp -pthread -lssl -lcrypto

// CMakeでの依存関係設定
/*
find_package(httplib REQUIRED)
target_link_libraries(your_target httplib::httplib)
*/

基本的なHTTPクライアント(GET/POST/PUT/DELETE)

#include "httplib.h"
#include <iostream>

int main() {
    // HTTPクライアントの作成
    httplib::Client client("https://api.example.com");
    
    // 基本的なGETリクエスト
    auto res = client.Get("/users");
    if (res) {
        if (res->status == 200) {
            std::cout << "Status: " << res->status << std::endl;
            std::cout << "Content-Type: " << res->get_header_value("content-type") << std::endl;
            std::cout << "Body: " << res->body << std::endl;
        }
    } else {
        auto err = res.error();
        std::cout << "HTTP error: " << httplib::to_string(err) << std::endl;
    }
    
    // クエリパラメータ付きGETリクエスト
    httplib::Params params = {
        {"page", "1"},
        {"limit", "10"},
        {"sort", "created_at"}
    };
    res = client.Get("/users", params, httplib::Headers{});
    
    // POSTリクエスト(JSON送信)
    std::string json_data = R"({
        "name": "田中太郎",
        "email": "[email protected]",
        "age": 30
    })";
    
    httplib::Headers headers = {
        {"Content-Type", "application/json"},
        {"Authorization", "Bearer your-token"}
    };
    
    res = client.Post("/users", headers, json_data, "application/json");
    if (res && res->status == 201) {
        std::cout << "ユーザー作成成功: " << res->body << std::endl;
    } else {
        std::cout << "エラー: " << (res ? std::to_string(res->status) : "Connection failed") << std::endl;
    }
    
    // POSTリクエスト(フォームデータ送信)
    httplib::Params form_data = {
        {"username", "testuser"},
        {"password", "secret123"}
    };
    res = client.Post("/login", form_data);
    
    // PUTリクエスト(データ更新)
    std::string update_json = R"({"name": "田中次郎", "email": "[email protected]"})";
    res = client.Put("/users/123", headers, update_json, "application/json");
    
    // DELETEリクエスト
    res = client.Delete("/users/123", headers);
    if (res && res->status == 204) {
        std::cout << "ユーザー削除完了" << std::endl;
    }
    
    // レスポンス詳細情報の確認
    if (res) {
        std::cout << "Status: " << res->status << std::endl;
        std::cout << "Reason: " << res->reason << std::endl;
        std::cout << "Headers:" << std::endl;
        for (const auto& [key, value] : res->headers) {
            std::cout << "  " << key << ": " << value << std::endl;
        }
    }
    
    return 0;
}

高度な設定とカスタマイズ(ヘッダー、認証、タイムアウト等)

#include "httplib.h"
#include <chrono>

void advanced_client_configuration() {
    // HTTPSクライアントの作成
    httplib::Client client("https://secure-api.example.com");
    
    // カスタムヘッダーの設定
    httplib::Headers custom_headers = {
        {"User-Agent", "MyApp/1.0 (cpp-httplib)"},
        {"Accept", "application/json"},
        {"Accept-Language", "ja-JP,en-US"},
        {"X-API-Version", "v2"},
        {"X-Request-ID", "req-12345"}
    };
    
    // デフォルトヘッダーの設定
    client.set_default_headers(custom_headers);
    
    // Basic認証の設定
    client.set_basic_auth("username", "password");
    
    // Bearer Token認証
    client.set_bearer_token_auth("your-jwt-token");
    
    // Digest認証(OpenSSL必須)
    client.set_digest_auth("username", "password");
    
    // タイムアウト設定
    client.set_connection_timeout(0, 300000); // 接続タイムアウト 300ms
    client.set_read_timeout(5, 0);            // 読み込みタイムアウト 5秒
    client.set_write_timeout(5, 0);           // 書き込みタイムアウト 5秒
    
    // SSL証明書設定
    client.set_ca_cert_path("./ca-bundle.crt");        // CA証明書バンドル
    client.enable_server_certificate_verification(true); // 証明書検証有効
    client.enable_server_hostname_verification(true);    // ホスト名検証有効
    
    // 開発環境でのSSL検証無効化(非推奨)
    // client.enable_server_certificate_verification(false);
    
    // プロキシ設定
    client.set_proxy("proxy.example.com", 8080);
    client.set_proxy_basic_auth("proxy_user", "proxy_pass");
    
    // Keep-Alive設定
    client.set_keep_alive(true);
    
    // リダイレクト追従設定
    client.set_follow_location(true);
    
    // 圧縮設定
    client.set_compress(true);      // リクエスト圧縮
    client.set_decompress(true);    // レスポンス自動展開
    
    // ネットワークインターフェース指定(Linux/macOS)
    client.set_interface("eth0");
    
    // リクエスト実行例
    auto res = client.Get("/secure-data");
    if (res) {
        std::cout << "Secure request successful: " << res->status << std::endl;
    }
}

// カスタム認証ヘッダーの実装
class APIKeyAuth {
private:
    std::string api_key;
    std::string header_name;
    
public:
    APIKeyAuth(const std::string& key, const std::string& header = "X-API-Key")
        : api_key(key), header_name(header) {}
    
    httplib::Headers get_headers() const {
        return {{header_name, api_key}};
    }
};

void custom_authentication_example() {
    httplib::Client client("https://api.example.com");
    
    // カスタム認証の使用
    APIKeyAuth auth("your-api-key-here");
    auto headers = auth.get_headers();
    
    auto res = client.Get("/protected-data", headers);
    if (res) {
        std::cout << "Authenticated request: " << res->status << std::endl;
    }
}

エラーハンドリングとリトライ機能

#include "httplib.h"
#include <chrono>
#include <thread>
#include <stdexcept>

// 包括的なエラーハンドリング
class HTTPClient {
private:
    httplib::Client client;
    int max_retries;
    std::chrono::milliseconds base_delay;
    
public:
    HTTPClient(const std::string& host, int port = -1, int retries = 3) 
        : client(host, port), max_retries(retries), base_delay(1000) {
        
        // 基本設定
        client.set_connection_timeout(0, 300000); // 300ms
        client.set_read_timeout(10, 0);          // 10秒
        client.set_write_timeout(10, 0);         // 10秒
    }
    
    httplib::Result safe_get(const std::string& path, 
                            const httplib::Headers& headers = {},
                            const httplib::Params& params = {}) {
        
        for (int attempt = 0; attempt <= max_retries; ++attempt) {
            auto res = client.Get(path, params, headers);
            
            if (res) {
                // 成功レスポンスの場合
                if (res->status >= 200 && res->status < 300) {
                    return res;
                }
                
                // リトライ対象ステータスコードの判定
                if (res->status == 429 || res->status == 500 || 
                    res->status == 502 || res->status == 503 || res->status == 504) {
                    
                    if (attempt < max_retries) {
                        auto delay = base_delay * (1 << attempt); // 指数バックオフ
                        std::cout << "リトライ " << (attempt + 1) << "/" << max_retries 
                                 << " (ステータス: " << res->status << ") "
                                 << delay.count() << "ms後に実行..." << std::endl;
                        std::this_thread::sleep_for(delay);
                        continue;
                    }
                }
                
                // リトライしないエラーまたは最大試行回数到達
                return res;
            } else {
                // 接続エラーの場合
                auto error = res.error();
                std::cout << "接続エラー: " << httplib::to_string(error) << std::endl;
                
                if (attempt < max_retries) {
                    auto delay = base_delay * (1 << attempt);
                    std::cout << "接続リトライ " << (attempt + 1) << "/" << max_retries 
                             << " " << delay.count() << "ms後に実行..." << std::endl;
                    std::this_thread::sleep_for(delay);
                    continue;
                }
            }
        }
        
        // 全試行失敗
        return httplib::Result{nullptr, httplib::Error::Unknown};
    }
    
    void handle_response(const httplib::Result& res) {
        if (!res) {
            auto error = res.error();
            
            switch (error) {
                case httplib::Error::Connection:
                    std::cerr << "接続エラー: サーバーに接続できません" << std::endl;
                    break;
                case httplib::Error::BindIPAddress:
                    std::cerr << "IPアドレスバインドエラー" << std::endl;
                    break;
                case httplib::Error::Read:
                    std::cerr << "読み込みエラー: データ受信に失敗" << std::endl;
                    break;
                case httplib::Error::Write:
                    std::cerr << "書き込みエラー: データ送信に失敗" << std::endl;
                    break;
                case httplib::Error::ExceedRedirectCount:
                    std::cerr << "リダイレクトエラー: リダイレクト上限超過" << std::endl;
                    break;
                case httplib::Error::Canceled:
                    std::cerr << "リクエストキャンセル" << std::endl;
                    break;
                case httplib::Error::SSLConnection:
                    std::cerr << "SSL接続エラー: HTTPS接続に失敗" << std::endl;
                    break;
                case httplib::Error::SSLLoadingCerts:
                    std::cerr << "SSL証明書読み込みエラー" << std::endl;
                    break;
                case httplib::Error::SSLServerVerification:
                    std::cerr << "SSL証明書検証エラー" << std::endl;
                    break;
                case httplib::Error::UnsupportedMultipartBoundaryChars:
                    std::cerr << "マルチパートバウンダリ文字エラー" << std::endl;
                    break;
                default:
                    std::cerr << "不明なエラー: " << httplib::to_string(error) << std::endl;
                    break;
            }
            return;
        }
        
        // ステータスコード別処理
        switch (res->status) {
            case 200:
                std::cout << "成功: " << res->body << std::endl;
                break;
            case 201:
                std::cout << "作成成功: " << res->body << std::endl;
                break;
            case 204:
                std::cout << "処理完了(レスポンスなし)" << std::endl;
                break;
            case 400:
                std::cerr << "バッドリクエスト: " << res->body << std::endl;
                break;
            case 401:
                std::cerr << "認証エラー: トークンを確認してください" << std::endl;
                break;
            case 403:
                std::cerr << "権限エラー: アクセス権限がありません" << std::endl;
                break;
            case 404:
                std::cerr << "見つかりません: リソースが存在しません" << std::endl;
                break;
            case 429:
                std::cerr << "レート制限: しばらく待ってから再試行してください" << std::endl;
                break;
            case 500:
                std::cerr << "サーバーエラー: サーバー側の問題です" << std::endl;
                break;
            default:
                if (res->status >= 400) {
                    std::cerr << "HTTPエラー " << res->status << ": " << res->body << std::endl;
                } else {
                    std::cout << "レスポンス " << res->status << ": " << res->body << std::endl;
                }
                break;
        }
    }
};

void error_handling_example() {
    try {
        HTTPClient client("https://api.example.com");
        
        // 通常のリクエスト
        auto res = client.safe_get("/users");
        client.handle_response(res);
        
        // 失敗する可能性のあるリクエスト
        res = client.safe_get("/unstable-endpoint");
        client.handle_response(res);
        
    } catch (const std::exception& e) {
        std::cerr << "例外発生: " << e.what() << std::endl;
    }
}

基本的なHTTPサーバー実装

#include "httplib.h"
#include <iostream>
#include <fstream>
#include <json/json.h>  // JsonCpp利用時

class SimpleHTTPServer {
private:
    httplib::Server server;
    
public:
    SimpleHTTPServer() {
        setup_routes();
        setup_middleware();
    }
    
    void setup_routes() {
        // 基本的なGETエンドポイント
        server.Get("/hello", [](const httplib::Request& req, httplib::Response& res) {
            res.set_content("Hello, World!", "text/plain");
        });
        
        // JSONレスポンス
        server.Get("/api/users", [](const httplib::Request& req, httplib::Response& res) {
            std::string json_response = R"({
                "users": [
                    {"id": 1, "name": "田中太郎", "email": "[email protected]"},
                    {"id": 2, "name": "佐藤花子", "email": "[email protected]"}
                ]
            })";
            res.set_content(json_response, "application/json");
        });
        
        // パスパラメータ付きルート
        server.Get(R"(/api/users/(\d+))", [](const httplib::Request& req, httplib::Response& res) {
            auto user_id = req.matches[1];
            std::string response = "User ID: " + std::string(user_id);
            res.set_content(response, "text/plain");
        });
        
        // 名前付きパスパラメータ
        server.Get("/users/:id", [](const httplib::Request& req, httplib::Response& res) {
            auto user_id = req.path_params.at("id");
            std::string response = "User ID: " + user_id;
            res.set_content(response, "text/plain");
        });
        
        // POSTエンドポイント(JSON受信)
        server.Post("/api/users", [](const httplib::Request& req, httplib::Response& res) {
            // Content-Typeチェック
            if (req.get_header_value("Content-Type") != "application/json") {
                res.status = 400;
                res.set_content("Content-Type must be application/json", "text/plain");
                return;
            }
            
            // リクエストボディの処理
            std::cout << "Received JSON: " << req.body << std::endl;
            
            // レスポンスの作成
            std::string response_json = R"({
                "status": "success",
                "message": "User created successfully",
                "id": 123
            })";
            
            res.status = 201;
            res.set_content(response_json, "application/json");
        });
        
        // マルチパートフォームデータ処理
        server.Post("/upload", [](const httplib::Request& req, httplib::Response& res) {
            if (req.is_multipart_form_data()) {
                for (const auto& file : req.files) {
                    std::cout << "File: " << file.first << std::endl;
                    std::cout << "  Filename: " << file.second.filename << std::endl;
                    std::cout << "  Content-Type: " << file.second.content_type << std::endl;
                    std::cout << "  Size: " << file.second.content.size() << " bytes" << std::endl;
                    
                    // ファイルを保存
                    std::ofstream ofs("./uploads/" + file.second.filename, std::ios::binary);
                    ofs << file.second.content;
                }
                
                res.set_content("Files uploaded successfully", "text/plain");
            } else {
                res.status = 400;
                res.set_content("Expected multipart/form-data", "text/plain");
            }
        });
        
        // ストリーミングレスポンス
        server.Get("/stream", [](const httplib::Request& req, httplib::Response& res) {
            res.set_chunked_content_provider(
                "text/plain",
                [](size_t offset, httplib::DataSink& sink) {
                    static int count = 0;
                    if (count < 10) {
                        std::string chunk = "Chunk " + std::to_string(count++) + "\n";
                        sink.write(chunk.c_str(), chunk.size());
                        return true;  // 継続
                    } else {
                        sink.done();
                        return false; // 完了
                    }
                }
            );
        });
        
        // 静的ファイルサーバー
        server.set_mount_point("/static", "./public");
        
        // サーバー停止エンドポイント
        server.Get("/stop", [&](const httplib::Request& req, httplib::Response& res) {
            res.set_content("Server stopping...", "text/plain");
            server.stop();
        });
    }
    
    void setup_middleware() {
        // リクエストロガー
        server.set_logger([](const httplib::Request& req, const httplib::Response& res) {
            std::cout << "[" << std::chrono::duration_cast<std::chrono::seconds>(
                std::chrono::system_clock::now().time_since_epoch()).count() 
                << "] " << req.method << " " << req.path 
                << " -> " << res.status << std::endl;
        });
        
        // CORS設定
        server.set_pre_routing_handler([](const httplib::Request& req, httplib::Response& res) {
            res.set_header("Access-Control-Allow-Origin", "*");
            res.set_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
            res.set_header("Access-Control-Allow-Headers", "Content-Type, Authorization");
            
            if (req.method == "OPTIONS") {
                res.status = 200;
                return httplib::Server::HandlerResponse::Handled;
            }
            return httplib::Server::HandlerResponse::Unhandled;
        });
        
        // エラーハンドラー
        server.set_error_handler([](const httplib::Request& req, httplib::Response& res) {
            std::string error_html = "<html><body><h1>Error " + 
                std::to_string(res.status) + "</h1><p>Something went wrong</p></body></html>";
            res.set_content(error_html, "text/html");
        });
        
        // 例外ハンドラー
        server.set_exception_handler([](const httplib::Request& req, httplib::Response& res, std::exception_ptr ep) {
            try {
                std::rethrow_exception(ep);
            } catch (const std::exception& e) {
                res.status = 500;
                std::string error_msg = "Internal Server Error: " + std::string(e.what());
                res.set_content(error_msg, "text/plain");
            } catch (...) {
                res.status = 500;
                res.set_content("Unknown Internal Server Error", "text/plain");
            }
        });
    }
    
    void run(const std::string& host = "localhost", int port = 8080) {
        std::cout << "サーバー開始: http://" << host << ":" << port << std::endl;
        
        if (!server.listen(host, port)) {
            std::cerr << "サーバー開始失敗" << std::endl;
        }
    }
};

int main() {
    SimpleHTTPServer server;
    server.run("0.0.0.0", 8080);
    return 0;
}

高度な機能(ファイルアップロード、ストリーミング、認証)

#include "httplib.h"
#include <fstream>
#include <filesystem>
#include <jwt-cpp/jwt.h>  // JWT認証ライブラリ利用時

class AdvancedHTTPServer {
private:
    httplib::Server server;
    std::string jwt_secret = "your-secret-key";
    
public:
    AdvancedHTTPServer() {
        setup_advanced_routes();
        configure_server();
    }
    
    bool verify_jwt_token(const std::string& token) {
        try {
            auto decoded = jwt::decode(token);
            auto verifier = jwt::verify()
                .allow_algorithm(jwt::algorithm::hs256{jwt_secret})
                .with_issuer("your-app");
            verifier.verify(decoded);
            return true;
        } catch (const std::exception& e) {
            std::cerr << "JWT verification failed: " << e.what() << std::endl;
            return false;
        }
    }
    
    void setup_advanced_routes() {
        // JWT認証が必要なエンドポイント
        server.Get("/api/protected", [this](const httplib::Request& req, httplib::Response& res) {
            std::string auth_header = req.get_header_value("Authorization");
            if (auth_header.empty() || auth_header.substr(0, 7) != "Bearer ") {
                res.status = 401;
                res.set_content("Missing or invalid Authorization header", "text/plain");
                return;
            }
            
            std::string token = auth_header.substr(7);
            if (!verify_jwt_token(token)) {
                res.status = 401;
                res.set_content("Invalid JWT token", "text/plain");
                return;
            }
            
            res.set_content("Protected data: Secret information", "text/plain");
        });
        
        // 大容量ファイルアップロード
        server.Post("/api/upload/large", [](const httplib::Request& req, httplib::Response& res) {
            std::string upload_dir = "./uploads";
            std::filesystem::create_directories(upload_dir);
            
            if (req.is_multipart_form_data()) {
                for (const auto& file : req.files) {
                    std::string filepath = upload_dir + "/" + file.second.filename;
                    
                    std::ofstream ofs(filepath, std::ios::binary);
                    if (ofs) {
                        ofs.write(file.second.content.data(), file.second.content.size());
                        std::cout << "ファイル保存完了: " << filepath 
                                 << " (" << file.second.content.size() << " bytes)" << std::endl;
                    } else {
                        res.status = 500;
                        res.set_content("File save failed", "text/plain");
                        return;
                    }
                }
                
                std::string response = "Upload completed: " + std::to_string(req.files.size()) + " files";
                res.set_content(response, "text/plain");
            } else {
                res.status = 400;
                res.set_content("Expected multipart/form-data", "text/plain");
            }
        });
        
        // コンテンツレシーバーによるストリーミング受信
        server.Post("/api/upload/stream", [](const httplib::Request& req, httplib::Response& res, 
                   const httplib::ContentReader& content_reader) {
            
            std::string filename = "streamed_file.dat";
            std::ofstream ofs(filename, std::ios::binary);
            
            if (!ofs) {
                res.status = 500;
                res.set_content("Cannot create file", "text/plain");
                return;
            }
            
            size_t total_bytes = 0;
            
            content_reader([&](const char* data, size_t data_length) {
                ofs.write(data, data_length);
                total_bytes += data_length;
                
                // 進捗表示(1MBごと)
                if (total_bytes % (1024 * 1024) == 0) {
                    std::cout << "Received: " << total_bytes / (1024 * 1024) << " MB" << std::endl;
                }
                
                return true; // 継続
            });
            
            ofs.close();
            
            std::string response = "File received: " + std::to_string(total_bytes) + " bytes";
            res.set_content(response, "text/plain");
        });
        
        // ファイルダウンロード(Range Request対応)
        server.Get(R"(/api/download/(.+))", [](const httplib::Request& req, httplib::Response& res) {
            std::string filename = req.matches[1];
            std::string filepath = "./downloads/" + filename;
            
            if (!std::filesystem::exists(filepath)) {
                res.status = 404;
                res.set_content("File not found", "text/plain");
                return;
            }
            
            // ファイルサイズ取得
            auto file_size = std::filesystem::file_size(filepath);
            
            // Range Requestの処理
            std::string range_header = req.get_header_value("Range");
            if (!range_header.empty()) {
                // "bytes=start-end" 形式の解析
                size_t start = 0, end = file_size - 1;
                
                if (range_header.substr(0, 6) == "bytes=") {
                    std::string range_spec = range_header.substr(6);
                    auto dash_pos = range_spec.find('-');
                    
                    if (dash_pos != std::string::npos) {
                        if (dash_pos > 0) {
                            start = std::stoull(range_spec.substr(0, dash_pos));
                        }
                        if (dash_pos + 1 < range_spec.length()) {
                            end = std::stoull(range_spec.substr(dash_pos + 1));
                        }
                    }
                }
                
                // 範囲の妥当性チェック
                if (start >= file_size || end >= file_size || start > end) {
                    res.status = 416; // Range Not Satisfiable
                    res.set_header("Content-Range", "bytes */" + std::to_string(file_size));
                    return;
                }
                
                // 部分コンテンツの送信
                std::ifstream ifs(filepath, std::ios::binary);
                ifs.seekg(start);
                
                size_t content_length = end - start + 1;
                std::vector<char> buffer(content_length);
                ifs.read(buffer.data(), content_length);
                
                res.status = 206; // Partial Content
                res.set_header("Content-Range", "bytes " + std::to_string(start) + "-" + 
                             std::to_string(end) + "/" + std::to_string(file_size));
                res.set_header("Accept-Ranges", "bytes");
                res.set_content(std::string(buffer.data(), content_length), "application/octet-stream");
            } else {
                // 全体ファイルの送信
                res.set_file_content(filepath);
                res.set_header("Accept-Ranges", "bytes");
            }
        });
        
        // リアルタイムデータストリーミング
        server.Get("/api/events", [](const httplib::Request& req, httplib::Response& res) {
            res.set_header("Content-Type", "text/event-stream");
            res.set_header("Cache-Control", "no-cache");
            res.set_header("Connection", "keep-alive");
            
            res.set_chunked_content_provider(
                "text/event-stream",
                [](size_t offset, httplib::DataSink& sink) {
                    static int event_count = 0;
                    
                    if (event_count < 10) {
                        auto now = std::chrono::system_clock::now();
                        auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(
                            now.time_since_epoch()).count();
                        
                        std::string event_data = "data: {\"event\": " + std::to_string(event_count) + 
                                               ", \"timestamp\": " + std::to_string(timestamp) + "}\n\n";
                        
                        sink.write(event_data.c_str(), event_data.size());
                        event_count++;
                        
                        std::this_thread::sleep_for(std::chrono::seconds(1));
                        return true;
                    } else {
                        sink.done();
                        return false;
                    }
                }
            );
        });
    }
    
    void configure_server() {
        // サーバー設定
        server.set_read_timeout(60, 0);        // 60秒
        server.set_write_timeout(60, 0);       // 60秒
        server.set_payload_max_length(100 * 1024 * 1024); // 100MB
        server.set_keep_alive_max_count(10);
        server.set_keep_alive_timeout(30);
        
        // スレッドプール設定
        server.new_task_queue = []() {
            return new httplib::ThreadPool(12); // 12スレッド
        };
    }
    
    void run_https(const std::string& cert_path, const std::string& key_path, 
                   const std::string& host = "0.0.0.0", int port = 8443) {
        
        httplib::SSLServer ssl_server(cert_path, key_path);
        
        // HTTPSサーバーに設定をコピー
        ssl_server = std::move(server);
        
        std::cout << "HTTPS サーバー開始: https://" << host << ":" << port << std::endl;
        
        if (!ssl_server.listen(host, port)) {
            std::cerr << "HTTPS サーバー開始失敗" << std::endl;
        }
    }
};

int main() {
    AdvancedHTTPServer server;
    
    // HTTPSサーバーとして実行(証明書ファイルが必要)
    // server.run_https("./cert.pem", "./key.pem");
    
    return 0;
}