Skip to main content

oxigdal_gateway/
lib.rs

1//! OxiGDAL API Gateway
2//!
3//! Enterprise-grade API gateway with comprehensive features for geospatial services.
4//!
5//! # Features
6//!
7//! - **Rate Limiting**: Token bucket, leaky bucket, fixed/sliding window algorithms
8//! - **Authentication**: API keys, JWT, OAuth2, session management, MFA
9//! - **API Versioning**: Multiple version support with negotiation and migration
10//! - **GraphQL**: Full GraphQL server with subscriptions and DataLoader
11//! - **WebSocket**: Connection multiplexing and message routing
12//! - **Middleware**: CORS, compression, caching, logging, metrics
13//! - **Load Balancing**: Multiple strategies with health checks and circuit breaker
14//! - **Transformation**: Request/response transformation and format adaptation
15//!
16//! # Example
17//!
18//! ```no_run
19//! use oxigdal_gateway::{Gateway, GatewayConfig};
20//!
21//! #[tokio::main]
22//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
23//!     let config = GatewayConfig::default();
24//!     let gateway = Gateway::new(config)?;
25//!     gateway.serve("0.0.0.0:8080").await?;
26//!     Ok(())
27//! }
28//! ```
29
30#![warn(missing_docs)]
31#![deny(clippy::unwrap_used, clippy::panic)]
32
33pub mod auth;
34pub mod error;
35pub mod graphql;
36pub mod loadbalancer;
37pub mod middleware;
38pub mod rate_limit;
39pub mod transform;
40pub mod versioning;
41pub mod websocket;
42
43pub use error::{GatewayError, Result};
44
45use std::net::SocketAddr;
46use std::sync::Arc;
47use tokio::net::TcpListener;
48
49/// Gateway configuration.
50#[derive(Debug, Clone)]
51pub struct GatewayConfig {
52    /// Rate limiting configuration
53    pub rate_limit: rate_limit::RateLimitConfig,
54    /// Authentication configuration
55    pub auth: auth::AuthConfig,
56    /// Load balancer configuration
57    pub loadbalancer: loadbalancer::LoadBalancerConfig,
58    /// Middleware configuration
59    pub middleware: middleware::MiddlewareConfig,
60    /// Maximum request body size in bytes
61    pub max_body_size: usize,
62    /// Request timeout in seconds
63    pub request_timeout: u64,
64    /// Enable GraphQL endpoint
65    pub enable_graphql: bool,
66    /// Enable WebSocket endpoint
67    pub enable_websocket: bool,
68}
69
70impl Default for GatewayConfig {
71    fn default() -> Self {
72        Self {
73            rate_limit: rate_limit::RateLimitConfig::default(),
74            auth: auth::AuthConfig::default(),
75            loadbalancer: loadbalancer::LoadBalancerConfig::default(),
76            middleware: middleware::MiddlewareConfig::default(),
77            max_body_size: 10 * 1024 * 1024, // 10MB
78            request_timeout: 30,
79            enable_graphql: true,
80            enable_websocket: true,
81        }
82    }
83}
84
85/// API Gateway instance.
86pub struct Gateway {
87    config: Arc<GatewayConfig>,
88}
89
90impl Gateway {
91    /// Creates a new gateway with the given configuration.
92    pub fn new(config: GatewayConfig) -> Result<Self> {
93        Ok(Self {
94            config: Arc::new(config),
95        })
96    }
97
98    /// Starts the gateway server on the given address.
99    pub async fn serve(self, addr: &str) -> Result<()> {
100        let addr: SocketAddr = addr
101            .parse()
102            .map_err(|e| GatewayError::ConfigError(format!("Invalid address: {}", e)))?;
103
104        let listener = TcpListener::bind(addr)
105            .await
106            .map_err(|e| GatewayError::InternalError(format!("Failed to bind: {}", e)))?;
107
108        tracing::info!("Gateway listening on {}", addr);
109
110        loop {
111            let (socket, remote_addr) = listener
112                .accept()
113                .await
114                .map_err(|e| GatewayError::InternalError(format!("Accept error: {}", e)))?;
115
116            tracing::debug!("Accepted connection from {}", remote_addr);
117
118            // Handle connection in a separate task
119            let config = Arc::clone(&self.config);
120            tokio::spawn(async move {
121                if let Err(e) = handle_connection(socket, config).await {
122                    tracing::error!("Connection error: {}", e);
123                }
124            });
125        }
126    }
127}
128
129async fn handle_connection(
130    _socket: tokio::net::TcpStream,
131    _config: Arc<GatewayConfig>,
132) -> Result<()> {
133    // Connection handling implementation
134    Ok(())
135}
136
137#[cfg(test)]
138mod tests {
139    use super::*;
140
141    #[test]
142    fn test_gateway_config_default() {
143        let config = GatewayConfig::default();
144        assert_eq!(config.max_body_size, 10 * 1024 * 1024);
145        assert_eq!(config.request_timeout, 30);
146        assert!(config.enable_graphql);
147        assert!(config.enable_websocket);
148    }
149
150    #[test]
151    fn test_gateway_creation() {
152        let config = GatewayConfig::default();
153        let gateway = Gateway::new(config);
154        assert!(gateway.is_ok());
155    }
156}