Build the axum router with all endpoints. JSON routes (all `/v1/` routes except SSE streams and the WebSocket endpoint) get `stamp_content_type` applied via `map_response` so every response carries `application/vnd.nodedb.v1+json; charset=utf-8` without per-handler boilerplate. SSE and WebSocket routes are kept on a separate sub-router that does NOT carry the `map_response` layer — those handler
(state: AppState)
| 66 | /// carry the `map_response` layer — those handlers set their own |
| 67 | /// `Content-Type` (text/event-stream, or the WS upgrade response). |
| 68 | fn build_router(state: AppState) -> Router { |
| 69 | // ── Streaming / non-JSON routes (no Content-Type stamp) ────────────────── |
| 70 | let streaming_routes = Router::new() |
| 71 | // WebSocket RPC — upgrade response, not JSON. |
| 72 | .route("/v1/ws", get(routes::ws_rpc::ws_handler)) |
| 73 | // SSE CDC stream — text/event-stream. |
| 74 | .route("/v1/cdc/{collection}", get(routes::cdc::sse_stream)) |
| 75 | // SSE named-stream events — text/event-stream. |
| 76 | .route( |
| 77 | "/v1/streams/{stream}/events", |
| 78 | get(routes::stream_sse::stream_events), |
| 79 | ); |
| 80 | |
| 81 | // ── JSON routes (Content-Type stamped to v1 vendor type) ───────────────── |
| 82 | let mut json_routes = Router::new() |
| 83 | .route("/v1/query", post(routes::query::query)) |
| 84 | .route("/v1/query/stream", post(routes::query::query_ndjson)) |
| 85 | .route("/v1/status", get(routes::status::status)) |
| 86 | .route("/v1/cluster/status", get(routes::cluster::cluster_status)) |
| 87 | .route( |
| 88 | "/v1/cluster/debug/raft/{group_id}", |
| 89 | get(routes::cluster_debug::raft::raft_debug), |
| 90 | ) |
| 91 | .route( |
| 92 | "/v1/cluster/debug/transport", |
| 93 | get(routes::cluster_debug::transport::transport_debug), |
| 94 | ) |
| 95 | .route( |
| 96 | "/v1/cluster/debug/catalog/descriptors", |
| 97 | get(routes::cluster_debug::catalog::catalog_debug), |
| 98 | ) |
| 99 | .route( |
| 100 | "/v1/cluster/debug/leases", |
| 101 | get(routes::cluster_debug::leases::leases_debug), |
| 102 | ) |
| 103 | .route( |
| 104 | "/v1/cluster/debug/quarantined-segments", |
| 105 | get(routes::cluster_debug::quarantined_segments::quarantined_segments), |
| 106 | ) |
| 107 | .route( |
| 108 | "/v1/auth/exchange-key", |
| 109 | post(routes::auth_key::exchange_key), |
| 110 | ) |
| 111 | .route( |
| 112 | "/v1/auth/session", |
| 113 | post(routes::auth_session::create_session).delete(routes::auth_session::delete_session), |
| 114 | ) |
| 115 | .route( |
| 116 | "/v1/collections/{name}/crdt/apply", |
| 117 | post(routes::crdt::crdt_apply), |
| 118 | ) |
| 119 | .route("/v1/cdc/{collection}/poll", get(routes::cdc::poll_changes)) |
| 120 | .route( |
| 121 | "/v1/streams/{stream}/poll", |
| 122 | get(routes::stream_poll::poll_stream), |
| 123 | ); |
| 124 | |
| 125 | json_routes = json_routes |