llm_edge_proxy/
server.rs

1//! HTTP server implementation
2//!
3//! Provides the core HTTP/HTTPS server for the proxy with full middleware stack.
4
5pub mod routes;
6pub mod tls;
7pub mod tracing;
8
9use crate::config::Config;
10use crate::error::ProxyError;
11use crate::middleware;
12use axum::{
13    routing::{get, post},
14    Router,
15};
16use std::net::SocketAddr;
17use tower_http::{compression::CompressionLayer, cors::CorsLayer, trace::TraceLayer};
18
19/// Build the Axum application with all middleware and routes
20pub async fn build_app(config: Config) -> Result<Router, ProxyError> {
21    // Build the router
22    let app = Router::new()
23        // Health check endpoints (no auth required by default)
24        .route("/health", get(routes::health_check))
25        .route("/health/ready", get(routes::readiness_check))
26        .route("/health/live", get(routes::liveness_check))
27        // Metrics endpoint (no auth required)
28        .route("/metrics", get(routes::metrics))
29        // Protected proxy endpoints
30        .route("/v1/chat/completions", post(routes::chat_completions))
31        .route("/v1/completions", post(routes::completions))
32        // NOTE: Rate limiting temporarily disabled due to tower_governor API compatibility
33        // TODO: Re-enable rate limiting once tower_governor integration is fixed
34        // .layer(middleware::create_rate_limiter(&config))
35        // Apply authentication middleware
36        .layer(axum::middleware::from_fn_with_state(
37            config.clone(),
38            middleware::auth_middleware,
39        ))
40        // Apply tower-http middleware
41        .layer(TraceLayer::new_for_http())
42        .layer(CompressionLayer::new())
43        .layer(CorsLayer::permissive())
44        // Add shared state
45        .with_state(config);
46
47    Ok(app)
48}
49
50/// Creates the main application router (legacy compatibility)
51pub fn create_router() -> Router {
52    Router::new()
53        .route("/health", get(routes::health_check))
54        .route("/health/ready", get(routes::readiness_check))
55}
56
57/// Starts the HTTP server
58pub async fn serve(addr: SocketAddr, router: Router) -> anyhow::Result<()> {
59    eprintln!("Starting server on {}", addr);
60
61    let listener = tokio::net::TcpListener::bind(addr).await?;
62    axum::serve(listener, router).await?;
63
64    Ok(())
65}