Files
cpp-httplib/docs-src/pages/ja/cookbook/s12-user-data.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

2.4 KiB

title, order, status
title order status
S12. res.user_dataでハンドラ間データを渡す 31 draft

Pre-requestハンドラで認証トークンをデコードして、その結果をルートハンドラで使いたい。こういう「ハンドラ間のデータ受け渡し」は、res.user_dataに任意の型を入れて解決します。

基本の使い方

struct AuthUser {
  std::string id;
  std::string name;
  bool is_admin;
};

svr.set_pre_request_handler(
  [](const httplib::Request &req, httplib::Response &res) {
    auto token = req.get_header_value("Authorization");
    auto user = decode_token(token); // 認証トークンをデコード
    res.user_data.set("user", user);
    return httplib::Server::HandlerResponse::Unhandled;
  });

svr.Get("/me", [](const httplib::Request &req, httplib::Response &res) {
  auto *user = res.user_data.get<AuthUser>("user");
  if (!user) {
    res.status = 401;
    return;
  }
  res.set_content("Hello, " + user->name, "text/plain");
});

user_data.set()で任意の型の値を保存し、user_data.get<T>()で取り出します。型を正しく指定しないとnullptrが返るので注意してください。

よくある型

std::string、数値、構造体、std::shared_ptrなど、コピーできる値なら何でも入れられます。

res.user_data.set("user_id", std::string{"42"});
res.user_data.set("is_admin", true);
res.user_data.set("started_at", std::chrono::steady_clock::now());

どこで設定し、どこで読むか

設定する側はset_pre_routing_handler()かset_pre_request_handler()、読む側は通常のルートハンドラ、という流れが一般的です。Pre-requestのほうがルーティング後に呼ばれるので、req.matched_routeと組み合わせて「このルートにマッチしたときだけセット」という書き方ができます。

注意点

user_dataはResponseに乗っています(req.user_dataではありません)。これは、ハンドラにはResponse&として可変参照が渡されるためです。一見不思議ですが、「ハンドラ間で共有する可変コンテキスト」だと考えると納得がいきます。

Warning: user_data.get<T>()は型が一致しないとnullptrを返します。保存時と取得時で同じ型を指定してください。AuthUserで入れてconst AuthUserで取ろうとすると失敗します。