Files
cpp-httplib/docs-src/pages/ja/cookbook/s11-pre-request.md
T
yhirose 9bfd2ddf1c Fix README and docs pages that no longer match the code
Bring the READMEs and the docs pages (en and ja) in line with the
current header:

- Fix the client sample that does not compile, the Transfer-Encoding
  statement for default headers, the verifier callback comment, the
  thread pool spawn rule, the sanitize_filename description, and the
  inverted Accept-Encoding sentence.
- Describe recent behaviour: TLS errors behind Read/Write failures,
  Host validation, Connection: close for a body without length,
  content_reader rules, refused CONNECT, WebSocketClient proxies,
  CPPHTTPLIB_INTERIM_RESPONSE_MAX_COUNT, the SSE event size limit, and
  the payload limit of the Stream API.
- Complete the API references of WebSocket, WebSocketClient and the
  stream:: helpers, and the SSE reconnect rules.
- Fix cookbook pages: keychain loading on every backend, received Close
  status, a multipart sample that trusted the client's file name, an
  echo sample that sent binary as text, SNI, pre-request handler scope,
  stop() with WebSocket handlers, and the thread pool notes.
- Restore the mutex in the LLM app's Chapter 5 code.
2026-10-18 10:13:57 -04:00

3.8 KiB

title, order, status
title order status
S11. Pre-request handlerでルート単位の認証を行う 30 draft

S09. 全ルートに共通の前処理をするで紹介したset_pre_routing_handler()はルーティングの前に呼ばれるので、「どのルートにマッチしたか」を知れません。ルートによって認証の有無を変えたい場合は、set_pre_request_handler()のほうが便利です。

Pre-routingとの違い

フック 呼ばれるタイミング ルート情報 リクエストボディ
set_pre_routing_handler ルーティングの前 取得できない まだ読まれていない
set_pre_request_handler ルーティング後、ルートハンドラの直前 req.matched_routeで取得可能 まだ読まれていない

Pre-requestハンドラなら、req.matched_routeに「マッチしたパターン文字列」が入っているので、ルートに応じて処理を変えられます。

Pre-requestハンドラが呼ばれる時点ではボディがまだ読まれていないので、認証に失敗したリクエストなどを、(巨大かもしれない)ボディを読み込む前に拒否できます。その代わり、req.bodyやボディから解析されるフォームフィールドはこの時点では参照できません。ヘッダ・パス・クエリパラメータ・req.matched_routeを使って判断してください。

Pre-requestハンドラが呼ばれるのは、ルートにマッチしたリクエストだけです。set_mount_point()で配信するファイルはルートのマッチングより前に返されるので、静的ファイルを守りたいときはPre-routingハンドラでチェックしてください。

ルートごとに認証を切り替える

svr.set_pre_request_handler(
  [](const httplib::Request &req, httplib::Response &res) {
    // /adminで始まるルートだけ認証を要求
    if (req.matched_route.rfind("/admin", 0) == 0) {
      auto token = req.get_header_value("Authorization");
      if (!is_admin_token(token)) {
        res.status = 403;
        res.set_content("forbidden", "text/plain");
        return httplib::Server::HandlerResponse::Handled;
      }
    }
    return httplib::Server::HandlerResponse::Unhandled;
  });

matched_routeはパスパラメーターを展開する前のパターン文字列(例: /admin/users/:id)です。特定の値ではなく、ルート定義のパターンで判定できるので、IDや名前に左右されません。

svr.WebSocket()で登録したルートでも、Pre-requestハンドラは呼ばれます。呼ばれるのは101 Switching Protocolsを返す前なので、Handledを返すとそのHTTPレスポンス(403など)がそのまま返り、WebSocketへのアップグレードは行われません。

サーバーはどのOriginからのハンドシェイクも受け付けます。ブラウザは別のサイトが始めたハンドシェイクにもCookieを付けて送るので、Cookieで接続を認証している場合は、req.get_header_value("Origin")が自分のオリジンかどうかもここで確認してください。

戻り値の意味

Pre-routingハンドラと同じく、HandlerResponseを返します。

  • Unhandled: 通常の処理を続行(ルートハンドラが呼ばれる)
  • Handled: ここで完了、ルートハンドラはスキップされる

認証情報を後続のハンドラに渡す

認証で取り出したユーザー情報などをルートハンドラに渡したいときは、res.user_dataを使います。詳しくはS12. res.user_dataでハンドラ間データを渡すを参照してください。