reifydb_sub_server_admin/
routes.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later
3
4//! HTTP router configuration for the admin server.
5
6use axum::{
7	Router,
8	routing::{get, post},
9};
10use tower::limit::ConcurrencyLimitLayer;
11use tower_http::trace::TraceLayer;
12
13use crate::{
14	handlers::{handle_auth_status, handle_execute, handle_login, handle_logout, serve_index, serve_static},
15	state::AdminState,
16};
17
18/// Create the admin router with all endpoints and middleware.
19///
20/// # Endpoints
21///
22/// - `GET /health` - Health check
23/// - `POST /v1/auth/login` - Login
24/// - `POST /v1/auth/logout` - Logout
25/// - `GET /v1/auth/status` - Auth status
26/// - `GET /v1/config` - Get config
27/// - `PUT /v1/config` - Update config
28/// - `POST /v1/execute` - Execute query
29/// - `GET /v1/metrics` - System metrics
30/// - `GET /` - Serve admin UI index
31/// - `GET /assets/*path` - Serve static assets
32/// - `GET /*path` - SPA fallback to index.html
33///
34/// # Middleware
35///
36/// Applied in order (outer to inner):
37/// 1. Tracing - Logs requests and responses
38/// 2. Concurrency limit - Prevents resource exhaustion
39pub fn router(state: AdminState) -> Router {
40	let max_connections = state.max_connections();
41
42	Router::new()
43		// Auth endpoints
44		.route("/v1/auth/login", post(handle_login))
45		.route("/v1/auth/logout", post(handle_logout))
46		.route("/v1/auth/status", get(handle_auth_status))
47		// Execute endpoint
48		.route("/v1/execute", post(handle_execute))
49		// Static file serving
50		.route("/", get(serve_index))
51		.route("/assets/{*path}", get(serve_static))
52		// SPA fallback - serve index.html for unknown routes (for client-side routing)
53		.fallback(serve_index)
54		// Apply middleware layers
55		.layer(TraceLayer::new_for_http())
56		.layer(ConcurrencyLimitLayer::new(max_connections))
57		.with_state(state)
58}