1#![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#[derive(Debug, Clone)]
51pub struct GatewayConfig {
52 pub rate_limit: rate_limit::RateLimitConfig,
54 pub auth: auth::AuthConfig,
56 pub loadbalancer: loadbalancer::LoadBalancerConfig,
58 pub middleware: middleware::MiddlewareConfig,
60 pub max_body_size: usize,
62 pub request_timeout: u64,
64 pub enable_graphql: bool,
66 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, request_timeout: 30,
79 enable_graphql: true,
80 enable_websocket: true,
81 }
82 }
83}
84
85pub struct Gateway {
87 config: Arc<GatewayConfig>,
88}
89
90impl Gateway {
91 pub fn new(config: GatewayConfig) -> Result<Self> {
93 Ok(Self {
94 config: Arc::new(config),
95 })
96 }
97
98 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 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 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}