|
22 | 22 | //! * [ndarray] provides [NumPy](https://numpy.orgq)-like n-dimensional arrays used in numerical |
23 | 23 | //! computation. |
24 | 24 |
|
25 | | -use std::{net::SocketAddr, process::exit, str::FromStr, time::Duration}; |
26 | | - |
27 | | -use axum::ServiceExt; |
28 | | -use axum_server::{tls_rustls::RustlsConfig, Handle}; |
29 | | -use clap::Parser; |
30 | | -use expanduser::expanduser; |
31 | | -use tokio::signal; |
32 | | -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; |
33 | | - |
34 | 25 | mod app; |
35 | 26 | mod array; |
| 27 | +mod cli; |
36 | 28 | mod error; |
37 | 29 | mod models; |
38 | 30 | mod operation; |
39 | 31 | mod operations; |
40 | 32 | mod s3_client; |
| 33 | +mod server; |
| 34 | +mod tracing; |
41 | 35 | mod validated_json; |
42 | 36 |
|
43 | | -/// S3 Active Storage Proxy command line interface |
44 | | -#[derive(Debug, Parser)] |
45 | | -struct CommandLineArgs { |
46 | | - /// The IP address on which the proxy should listen |
47 | | - #[arg(long, default_value = "0.0.0.0", env = "S3_ACTIVE_STORAGE_HOST")] |
48 | | - host: String, |
49 | | - /// The port to which the proxy should bind |
50 | | - #[arg(long, default_value_t = 8080, env = "S3_ACTIVE_STORAGE_PORT")] |
51 | | - port: u16, |
52 | | - /// Flag indicating whether HTTPS should be used |
53 | | - #[arg(long, default_value_t = false, env = "S3_ACTIVE_STORAGE_HTTPS")] |
54 | | - https: bool, |
55 | | - /// Path to the certificate file to be used for HTTPS encryption |
56 | | - #[arg( |
57 | | - long, |
58 | | - default_value = "~/.config/s3-active-storage/certs/cert.pem", |
59 | | - env = "S3_ACTIVE_STORAGE_CERT_FILE" |
60 | | - )] |
61 | | - cert_file: String, |
62 | | - /// Path to the key file to be used for HTTPS encryption |
63 | | - #[arg( |
64 | | - long, |
65 | | - default_value = "~/.config/s3-active-storage/certs/key.pem", |
66 | | - env = "S3_ACTIVE_STORAGE_KEY_FILE" |
67 | | - )] |
68 | | - key_file: String, |
69 | | - /// Maximum time in seconds to wait for operations to complete upon receiving `ctrl+c` signal. |
70 | | - #[arg(long, default_value_t = 60, env = "S3_ACTIVE_STORAGE_SHUTDOWN_TIMEOUT")] |
71 | | - graceful_shutdown_timeout: u64, |
72 | | -} |
73 | | - |
74 | 37 | /// Application entry point |
75 | 38 | #[tokio::main] |
76 | 39 | async fn main() { |
77 | | - let args = CommandLineArgs::parse(); |
78 | | - |
79 | | - init_tracing(); |
80 | | - |
| 40 | + let args = cli::parse(); |
| 41 | + tracing::init_tracing(); |
81 | 42 | let service = app::service(); |
82 | | - let addr = SocketAddr::from_str(&format!("{}:{}", args.host, args.port)) |
83 | | - .expect("invalid host name, IP address or port number"); |
84 | | - |
85 | | - // Catch ctrl+c and try to shutdown gracefully |
86 | | - let handle = Handle::new(); |
87 | | - tokio::spawn(shutdown_signal( |
88 | | - handle.clone(), |
89 | | - args.graceful_shutdown_timeout, |
90 | | - )); |
91 | | - |
92 | | - if args.https { |
93 | | - // Expand files |
94 | | - let abs_cert_file = expanduser(args.cert_file) |
95 | | - .expect("Failed to expand ~ to user name. Please provide an absolute path instead.") |
96 | | - .canonicalize() |
97 | | - .expect("failed to determine absolute path to TLS cerficate file"); |
98 | | - let abs_key_file = expanduser(args.key_file) |
99 | | - .expect("Failed to expand ~ to user name. Please provide an absolute path instead.") |
100 | | - .canonicalize() |
101 | | - .expect("failed to determine absolute path to TLS key file"); |
102 | | - // Check files exist |
103 | | - if !abs_cert_file.exists() { |
104 | | - println!( |
105 | | - "TLS certificate file expected at '{}' but not found.", |
106 | | - abs_cert_file.display() |
107 | | - ); |
108 | | - exit(1) |
109 | | - } |
110 | | - if !abs_key_file.exists() { |
111 | | - println!( |
112 | | - "TLS key file expected at '{}' but not found.", |
113 | | - abs_key_file.display() |
114 | | - ); |
115 | | - exit(1) |
116 | | - } |
117 | | - // Set up TLS config |
118 | | - let tls_config = RustlsConfig::from_pem_file(abs_cert_file, abs_key_file) |
119 | | - .await |
120 | | - .expect("Failed to load TLS certificate files"); |
121 | | - // run HTTPS server with hyper |
122 | | - axum_server::bind_rustls(addr, tls_config) |
123 | | - .handle(handle) |
124 | | - .serve(service.into_make_service()) |
125 | | - .await |
126 | | - .unwrap(); |
127 | | - } else { |
128 | | - // run HTTP server with hyper |
129 | | - axum_server::bind(addr) |
130 | | - .handle(handle) |
131 | | - .serve(service.into_make_service()) |
132 | | - .await |
133 | | - .unwrap(); |
134 | | - } |
135 | | -} |
136 | | - |
137 | | -/// Initlialise tracing (logging) |
138 | | -/// |
139 | | -/// Applies a filter based on the `RUST_LOG` environment variable, falling back to enable debug |
140 | | -/// logging for this crate and tower_http if not set. |
141 | | -fn init_tracing() { |
142 | | - tracing_subscriber::registry() |
143 | | - .with( |
144 | | - tracing_subscriber::EnvFilter::try_from_default_env() |
145 | | - .unwrap_or_else(|_| "s3_active_storage=debug,tower_http=debug".into()), |
146 | | - ) |
147 | | - .with(tracing_subscriber::fmt::layer()) |
148 | | - .init(); |
149 | | -} |
150 | | - |
151 | | -/// Graceful shutdown handler |
152 | | -/// |
153 | | -/// Installs signal handlers to catch Ctrl-C or SIGTERM and trigger a graceful shutdown. |
154 | | -async fn shutdown_signal(handle: Handle, timeout: u64) { |
155 | | - let ctrl_c = async { |
156 | | - signal::ctrl_c() |
157 | | - .await |
158 | | - .expect("failed to install Ctrl+C handler"); |
159 | | - }; |
160 | | - |
161 | | - #[cfg(unix)] |
162 | | - let terminate = async { |
163 | | - signal::unix::signal(signal::unix::SignalKind::terminate()) |
164 | | - .expect("failed to install signal handler") |
165 | | - .recv() |
166 | | - .await; |
167 | | - }; |
168 | | - |
169 | | - #[cfg(not(unix))] |
170 | | - let terminate = std::future::pending::<()>(); |
171 | | - |
172 | | - tokio::select! { |
173 | | - _ = ctrl_c => {}, |
174 | | - _ = terminate => {}, |
175 | | - } |
176 | | - |
177 | | - println!("signal received, starting graceful shutdown"); |
178 | | - // Force shutdown if graceful shutdown takes longer than 10s |
179 | | - handle.graceful_shutdown(Some(Duration::from_secs(timeout))); |
| 43 | + server::serve(&args, service).await; |
180 | 44 | } |
0 commit comments