llm_registry_api/lib.rs
1//! LLM Registry API Layer
2//!
3//! This crate provides the REST API layer for the LLM Registry using Axum.
4//! It includes request handlers, middleware, error handling, and response types.
5//!
6//! # Architecture
7//!
8//! The API layer is organized into:
9//!
10//! - **Handlers**: Request handlers for all API endpoints
11//! - **Routes**: Route definitions and router configuration
12//! - **Middleware**: Tower middleware for logging, CORS, compression, etc.
13//! - **Error Handling**: Conversion of service errors to HTTP responses
14//! - **Responses**: Standard response wrappers and types
15//!
16//! # Example
17//!
18//! ```rust,no_run
19//! use llm_registry_api::{build_router, AppState};
20//! use llm_registry_service::ServiceRegistry;
21//! use std::sync::Arc;
22//!
23//! # async fn example(
24//! # services: ServiceRegistry,
25//! # ) {
26//! // Create application state
27//! let state = AppState::new(services);
28//!
29//! // Build router
30//! let app = build_router(state);
31//!
32//! // Run server (example)
33//! // axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
34//! // .serve(app.into_make_service())
35//! // .await
36//! // .unwrap();
37//! # }
38//! ```
39
40pub mod auth;
41pub mod auth_handlers;
42pub mod error;
43pub mod graphql;
44pub mod grpc;
45pub mod handlers;
46pub mod jwt;
47pub mod metrics_middleware;
48pub mod middleware;
49pub mod rate_limit;
50pub mod rbac;
51pub mod responses;
52pub mod routes;
53
54// Re-export main types for convenience
55pub use auth::{AuthState, AuthUser, optional_auth, require_auth, require_role};
56pub use auth_handlers::{AuthHandlerState, LoginRequest, LoginResponse, RefreshTokenRequest};
57pub use error::{ApiError, ApiResult, ErrorResponse};
58pub use graphql::{
59 build_schema, graphql_handler, graphql_playground, AppSchema, Mutation as GraphQLMutation,
60 Query as GraphQLQuery,
61};
62pub use grpc::{build_grpc_server, serve_grpc, RegistryServiceImpl, RegistryServiceServer};
63pub use handlers::{AppState, VersionInfo};
64pub use jwt::{Claims, JwtConfig, JwtManager, TokenPair};
65pub use middleware::{CorsConfig, MiddlewareConfig, UuidRequestIdGenerator};
66pub use rate_limit::{rate_limit, RateLimitConfig, RateLimiterState};
67pub use rbac::{Permission, RbacPolicy, Role};
68pub use responses::{
69 created, deleted, no_content, ok, ApiResponse, ComponentHealth, EmptyResponse, HealthResponse,
70 HealthStatus, PaginatedResponse, ResponseMeta,
71};
72pub use routes::{build_router, build_router_with_auth, build_router_with_graphql, RouteConfig};
73
74use axum::Router;
75use llm_registry_service::ServiceRegistry;
76
77/// Build a complete API server with middleware
78///
79/// This is a convenience function that builds a router with all middleware
80/// configured using default settings.
81///
82/// # Arguments
83///
84/// * `services` - The service registry to use
85///
86/// # Example
87///
88/// ```rust,no_run
89/// use llm_registry_api::build_api_server;
90/// use llm_registry_service::ServiceRegistry;
91/// use std::sync::Arc;
92///
93/// # async fn example(services: ServiceRegistry) {
94/// let app = build_api_server(services);
95/// # }
96/// ```
97pub fn build_api_server(services: ServiceRegistry) -> Router {
98 let state = AppState::new(services);
99 let router = build_router(state);
100
101 // Apply middleware layers
102 router
103 .layer(middleware::cors_layer())
104 .layer(tower_http::compression::CompressionLayer::new())
105 .layer(middleware::trace_layer())
106 .layer(tower_http::request_id::SetRequestIdLayer::x_request_id(
107 middleware::UuidRequestIdGenerator::default(),
108 ))
109 .layer(tower_http::request_id::PropagateRequestIdLayer::x_request_id())
110}
111
112/// Build API server with custom middleware configuration
113///
114/// # Arguments
115///
116/// * `services` - The service registry to use
117/// * `middleware_config` - Custom middleware configuration
118///
119/// # Example
120///
121/// ```rust,no_run
122/// use llm_registry_api::{build_api_server_with_config, MiddlewareConfig, CorsConfig};
123/// use llm_registry_service::ServiceRegistry;
124///
125/// # async fn example(services: ServiceRegistry) {
126/// let middleware_config = MiddlewareConfig::new()
127/// .with_compression(true)
128/// .with_timeout(60);
129///
130/// let app = build_api_server_with_config(services, middleware_config);
131/// # }
132/// ```
133pub fn build_api_server_with_config(
134 services: ServiceRegistry,
135 middleware_config: MiddlewareConfig,
136) -> Router {
137 let state = AppState::new(services);
138 let mut router = build_router(state);
139
140 // Apply CORS if configured
141 router = router.layer(middleware_config.cors.into_layer());
142
143 // Apply compression if enabled
144 if middleware_config.enable_compression {
145 router = router.layer(tower_http::compression::CompressionLayer::new());
146 }
147
148 // Apply tracing if enabled
149 if middleware_config.enable_tracing {
150 router = router.layer(
151 tower_http::trace::TraceLayer::new_for_http()
152 .make_span_with(
153 tower_http::trace::DefaultMakeSpan::new()
154 .include_headers(true)
155 .level(tracing::Level::INFO),
156 )
157 .on_response(
158 tower_http::trace::DefaultOnResponse::new()
159 .include_headers(true)
160 .latency_unit(tower_http::LatencyUnit::Millis)
161 .level(tracing::Level::INFO),
162 ),
163 );
164 }
165
166 // Apply request ID generation
167 router = router
168 .layer(tower_http::request_id::SetRequestIdLayer::x_request_id(
169 middleware::UuidRequestIdGenerator::default(),
170 ))
171 .layer(tower_http::request_id::PropagateRequestIdLayer::x_request_id());
172
173 router
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn test_library_compiles() {
182 // This test just verifies the library compiles
183 // Actual functionality tests would require mock services
184 }
185}