Files
cpp-httplib/docs-src/pages/ja/tour/02-basic-client.md
yhirose 885ed54b10 Unify spacing and wording in the Japanese docs pages
Drop the spaces between Japanese text and inline code or alphanumerics
in the tour and the few other pages that still had them, and reword
sentences that read awkwardly. The client compression page now lists
Zstd alongside zlib and Brotli.
2026-10-08 20:39:13 -04:00

7.9 KiB
Raw Blame History

title, order
title order
Basic Client 2

cpp-httplibはサーバーだけでなく、HTTPクライアント機能も備えています。httplib::Clientを使って、GETやPOSTリクエストを送ってみましょう。

テスト用サーバーの準備

クライアントの動作を確認するために、リクエストを受け付けるサーバーを用意します。次のコードを保存し、前章と同じ手順でコンパイル・実行してください。サーバーの詳しい解説は次章で行います。

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

int main() {
    httplib::Server svr;

    svr.Get("/hi", [](const auto &, auto &res) {
        res.set_content("Hello!", "text/plain");
    });

    svr.Get("/search", [](const auto &req, auto &res) {
        auto q = req.get_param_value("q");
        res.set_content("Query: " + q, "text/plain");
    });

    svr.Post("/post", [](const auto &req, auto &res) {
        res.set_content(req.body, "text/plain");
    });

    svr.Post("/submit", [](const auto &req, auto &res) {
        std::string result;
        for (auto &[key, val] : req.params) {
            result += key + " = " + val + "\n";
        }
        res.set_content(result, "text/plain");
    });

    svr.Post("/upload", [](const auto &req, auto &res) {
        auto f = req.form.get_file("file");
        auto content = f.filename + " (" + std::to_string(f.content.size()) + " bytes)";
        res.set_content(content, "text/plain");
    });

    svr.Get("/users/:id", [](const auto &req, auto &res) {
        auto id = req.path_params.at("id");
        res.set_content("User ID: " + id, "text/plain");
    });

    svr.Get(R"(/files/(\d+))", [](const auto &req, auto &res) {
        auto id = req.matches[1];
        res.set_content("File ID: " + std::string(id), "text/plain");
    });

    std::cout << "Listening on port 8080..." << std::endl;
    svr.listen("0.0.0.0", 8080);
}

GETリクエスト

サーバーが起動したら、別のターミナルを開いて試してみましょう。まず、最もシンプルなGETリクエストです。

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

int main() {
    httplib::Client cli("http://localhost:8080");

    auto res = cli.Get("/hi");
    if (res) {
        std::cout << res->status << std::endl;  // 200
        std::cout << res->body << std::endl;    // Hello!
    }
}

httplib::Clientのコンストラクターにサーバーのアドレスを渡し、Get()でリクエストを送ります。戻り値のresからステータスコードやボディを取得できます。

対応するcurlコマンドはこうなります。

curl http://localhost:8080/hi
# Hello!

レスポンスの確認

レスポンスには、ステータスコードとボディ以外にもヘッダー情報が含まれています。

auto res = cli.Get("/hi");
if (res) {
    // ステータスコード
    std::cout << res->status << std::endl;  // 200

    // ボディ
    std::cout << res->body << std::endl;  // Hello!

    // ヘッダー
    std::cout << res->get_header_value("Content-Type") << std::endl;  // text/plain
}

res->bodyはstd::stringなので、JSONレスポンスをパースしたい場合はnlohmann/jsonなどのJSONライブラリにそのまま渡せます。

クエリパラメーター

GETリクエストにクエリパラメーターを付けるには、URLに直接書くか、httplib::Paramsを使います。

auto res = cli.Get("/search", httplib::Params{{"q", "cpp-httplib"}});
if (res) {
    std::cout << res->body << std::endl;  // Query: cpp-httplib
}

httplib::Paramsを使うと、特殊文字のURLエンコードを自動で行ってくれます。

curl "http://localhost:8080/search?q=cpp-httplib"
# Query: cpp-httplib

パスパラメーター

URLのパスに値を直接埋め込む場合も、クライアント側は特別なAPIは不要です。パスをそのままGet()に渡すだけです。

auto res = cli.Get("/users/42");
if (res) {
    std::cout << res->body << std::endl;  // User ID: 42
}
curl http://localhost:8080/users/42
# User ID: 42

テスト用サーバーには、正規表現でIDを数字のみに絞った/files/(\d+)もあります。

auto res = cli.Get("/files/42");
if (res) {
    std::cout << res->body << std::endl;  // File ID: 42
}
curl http://localhost:8080/files/42
# File ID: 42

/files/abcのように数字以外を渡すと404が返ります。仕組みは次章で解説します。

リクエストヘッダー

カスタムHTTPヘッダーを付けるには、httplib::Headersを渡します。Get()やPost()のどちらでも使えます。

auto res = cli.Get("/hi", httplib::Headers{
    {"Authorization", "Bearer my-token"}
});
curl -H "Authorization: Bearer my-token" http://localhost:8080/hi

POSTリクエスト

テキストデータをPOSTしてみましょう。Post()の第2引数にボディ、第3引数にContent-Typeを指定します。

auto res = cli.Post("/post", "Hello, Server!", "text/plain");
if (res) {
    std::cout << res->status << std::endl;  // 200
    std::cout << res->body << std::endl;    // Hello, Server!
}

テスト用サーバーの/postはボディをそのまま返すので、送った文字列がそのまま返ってきます。

curl -X POST -H "Content-Type: text/plain" -d "Hello, Server!" http://localhost:8080/post
# Hello, Server!

フォームデータの送信

HTMLフォームのように、キーと値のペアを送ることもできます。httplib::Paramsを使います。

auto res = cli.Post("/submit", httplib::Params{
    {"name", "Alice"},
    {"age", "30"}
});
if (res) {
    std::cout << res->body << std::endl;
    // name = Alice
    // age = 30
}

これはapplication/x-www-form-urlencoded形式で送信されます。

curl -X POST -d "name=Alice&age=30" http://localhost:8080/submit

ファイルのPOST

ファイルをアップロードするには、httplib::UploadFormDataItemsを使ってマルチパートフォームデータとして送信します。

auto res = cli.Post("/upload", httplib::UploadFormDataItems{
    {"file", "Hello, File!", "hello.txt", "text/plain"}
});
if (res) {
    std::cout << res->body << std::endl;  // hello.txt (12 bytes)
}

UploadFormDataItemsの各要素は{name, content, filename, content_type}の4つのフィールドで構成されます。

curl -F "file=Hello, File!;filename=hello.txt;type=text/plain" http://localhost:8080/upload

エラーハンドリング

ネットワーク通信では、サーバーに接続できない場合があります。resが有効かどうかを必ず確認しましょう。

httplib::Client cli("http://localhost:9999");  // 存在しないポート
auto res = cli.Get("/hi");

if (!res) {
    // 接続エラー
    std::cout << "Error: " << httplib::to_string(res.error()) << std::endl;
    // Error: Could not establish connection
    return 1;
}

// ここに到達すればレスポンスを受信できている
if (res->status != 200) {
    std::cout << "HTTP Error: " << res->status << std::endl;
    return 1;
}

std::cout << res->body << std::endl;

エラーには2つのレベルがあります。

  • 接続エラー: サーバーに到達できなかった場合。resが偽になり、res.error()でエラーの種類を取得できます
  • HTTPエラー: サーバーからエラーステータス(404、500など)が返ってきた場合。resは真ですが、res->statusを確認する必要があります

次のステップ

クライアントからリクエストを送る方法がわかりました。次は、サーバー側をもっと詳しく見てみましょう。ルーティングやパスパラメータなど、サーバーの機能を掘り下げます。

次: Basic Server