1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/// Production configuration example
///
/// This example demonstrates:
/// - Environment-based configuration
/// - Logging setup
/// - Error handling
/// - Graceful shutdown
/// - Health monitoring
/// - Production-ready settings
///
/// Run with: cargo run --example production_config
use tideway::{App, ConfigBuilder, CorsConfig, RateLimitConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize structured logging early
// Production: Use JSON logging for log aggregation systems
let _log_json = std::env::var("TIDEWAY_LOG_JSON")
.map(|v| v.parse().unwrap_or(false))
.unwrap_or(false);
tideway::init_tracing();
// Load configuration from environment
// Production: Use ConfigBuilder to load from environment variables
let base_config = ConfigBuilder::new()
.from_env() // Loads from TIDEWAY_* env vars
.build()
.unwrap();
// Override CORS for production
let cors = if cfg!(debug_assertions) {
// Development: permissive
CorsConfig::permissive()
} else {
// Production: restrictive
let allowed_origins = std::env::var("ALLOWED_ORIGINS")
.unwrap_or_else(|_| "https://app.example.com".to_string())
.split(',')
.map(|s| s.trim().to_string())
.collect();
CorsConfig::restrictive(allowed_origins)
};
// Configure rate limiting for production
let rate_limit = RateLimitConfig::builder()
.enabled(true)
.max_requests(
std::env::var("RATE_LIMIT_MAX_REQUESTS")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(100),
)
.window_seconds(
std::env::var("RATE_LIMIT_WINDOW_SECONDS")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(60),
)
.per_ip() // Per-IP limiting in production
.build();
// Build final config
let config = ConfigBuilder::new()
.with_host(&base_config.server.host)
.with_port(base_config.server.port)
.with_log_level(&base_config.logging.level)
.with_json_logging(base_config.logging.json)
.with_cors(cors)
.with_rate_limit(rate_limit)
.build();
// Create app with production config
let app = App::with_config(config.unwrap());
// Log startup information
tracing::info!("Starting production server");
tracing::info!(
"Environment: {}",
if cfg!(debug_assertions) {
"development"
} else {
"production"
}
);
tracing::info!("Server ready and listening");
// Start server with graceful shutdown
// Ctrl+C and SIGTERM are handled automatically
match app.serve().await {
Ok(()) => {
tracing::info!("Server shut down gracefully");
Ok(())
}
Err(e) => {
tracing::error!("Server error: {}", e);
Err(Box::new(e) as Box<dyn std::error::Error>)
}
}
}