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}