diff --git a/README-websocket.md b/README-websocket.md index 657fd325..3629a59b 100644 --- a/README-websocket.md +++ b/README-websocket.md @@ -343,6 +343,18 @@ svr.WebSocket("/ws", [](const httplib::Request &req, httplib::ws::WebSocket &ws) }); ``` +The check above runs after the handshake, so the client sees a successful upgrade followed by a close frame. To refuse the upgrade itself with an HTTP status, use a pre-routing or pre-request handler. Both run before the `101 Switching Protocols` response, and `req.matched_route` is available in the pre-request handler: + +```cpp +svr.set_pre_request_handler([](const httplib::Request &req, httplib::Response &res) { + if (req.matched_route == "/ws" && req.get_header_value("Authorization").empty()) { + res.status = httplib::StatusCode::Unauthorized_401; + return httplib::Server::HandlerResponse::Handled; // not upgraded + } + return httplib::Server::HandlerResponse::Unhandled; +}); +``` + ### Custom Headers and Timeouts ```cpp diff --git a/README.md b/README.md index 4aff3ab2..791effe3 100644 --- a/README.md +++ b/README.md @@ -587,6 +587,8 @@ Request received Use `pre_routing_handler` to reject a request as early as possible, before the route is known. Use `pre_request_handler` for route-specific checks, since `req.matched_route` is available and the body has not been read yet. +A WebSocket upgrade request that matches a route registered with `svr.WebSocket()` takes a shorter path: `pre_routing_handler`, then route matching (`req.matched_route` is set), then `pre_request_handler`, then the WebSocket handler. If either hook returns `Handled`, its response is sent as a regular HTTP response and the connection is not upgraded. Once the connection is upgraded, `post_routing_handler` does not run. + ### Response user data `res.user_data` is a type-safe key-value store that lets pre-routing or pre-request handlers pass arbitrary data to route handlers. diff --git a/docs-src/pages/en/cookbook/s11-pre-request.md b/docs-src/pages/en/cookbook/s11-pre-request.md index 478c6b24..c6a5e76f 100644 --- a/docs-src/pages/en/cookbook/s11-pre-request.md +++ b/docs-src/pages/en/cookbook/s11-pre-request.md @@ -37,6 +37,8 @@ svr.set_pre_request_handler( `matched_route` is the pattern **before** path parameters are expanded (e.g. `/admin/users/:id`). You compare against the route definition, not the actual request path, so IDs or names don't throw you off. +The pre-request handler also runs for routes registered with `svr.WebSocket()`. It is called before the `101 Switching Protocols` response, so returning `Handled` sends your HTTP response (such as a 403) and the connection is never upgraded. + ## Return values Same as pre-routing — return `HandlerResponse`. diff --git a/docs-src/pages/en/tour/08-websocket.md b/docs-src/pages/en/tour/08-websocket.md index edb03c4b..6f245c75 100644 --- a/docs-src/pages/en/tour/08-websocket.md +++ b/docs-src/pages/en/tour/08-websocket.md @@ -107,6 +107,8 @@ svr.WebSocket("/ws", [](const httplib::Request &req, httplib::ws::WebSocket &ws) }); ``` +A check inside the handler runs after the handshake has completed. To refuse the connection with an HTTP status such as 401 before it is upgraded, use `set_pre_request_handler()` instead. It also runs for WebSocket routes. See [S11. Authenticate per route with a pre-request handler](../../cookbook/s11-pre-request). + ## Using WSS WebSocket over HTTPS (WSS) is also supported. On the server side, just register a WebSocket handler on `httplib::SSLServer`. diff --git a/docs-src/pages/ja/cookbook/s11-pre-request.md b/docs-src/pages/ja/cookbook/s11-pre-request.md index 1f5b6f52..651c6239 100644 --- a/docs-src/pages/ja/cookbook/s11-pre-request.md +++ b/docs-src/pages/ja/cookbook/s11-pre-request.md @@ -37,6 +37,8 @@ svr.set_pre_request_handler( `matched_route`はパスパラメーターを展開する**前**のパターン文字列(例: `/admin/users/:id`)です。特定の値ではなく、ルート定義のパターンで判定できるので、IDや名前に左右されません。 +`svr.WebSocket()`で登録したルートでも、Pre-requestハンドラは呼ばれます。呼ばれるのは`101 Switching Protocols`を返す前なので、`Handled`を返すとそのHTTPレスポンス(403など)がそのまま返り、WebSocketへのアップグレードは行われません。 + ## 戻り値の意味 Pre-routingハンドラと同じく、`HandlerResponse`を返します。 diff --git a/docs-src/pages/ja/tour/08-websocket.md b/docs-src/pages/ja/tour/08-websocket.md index e42bf3dd..ee893bb4 100644 --- a/docs-src/pages/ja/tour/08-websocket.md +++ b/docs-src/pages/ja/tour/08-websocket.md @@ -107,6 +107,8 @@ svr.WebSocket("/ws", [](const httplib::Request &req, httplib::ws::WebSocket &ws) }); ``` +ハンドラー内のチェックは、ハンドシェイクが完了した後に行われます。アップグレードする前に401などのHTTPステータスで接続を拒否したい場合は、`set_pre_request_handler()`を使ってください。WebSocketのルートでも呼ばれます。詳しくは[S11. Pre-request handlerでルート単位の認証を行う](../../cookbook/s11-pre-request)を参照してください。 + ## WSSで使う HTTPS上のWebSocket(WSS)にも対応しています。サーバー側は `httplib::SSLServer` にWebSocketハンドラーを登録するだけです。