sylvia_iot_corelib/
server_config.rs

1//! The top level configuration `server`.
2
3use std::env;
4
5use clap::{builder::RangedU64ValueParser, Arg, ArgMatches, Command};
6use serde::Deserialize;
7
8/// Server configuration object.
9#[derive(Default, Deserialize)]
10pub struct Config {
11    /// HTTP port.
12    ///
13    /// Default is `1080`.
14    #[serde(rename = "httpPort")]
15    pub http_port: Option<u16>,
16    /// HTTPS port.
17    ///
18    /// Default is `1443`.
19    #[serde(rename = "httpsPort")]
20    pub https_port: Option<u16>,
21    /// HTTPS CA certificate file path.
22    #[serde(rename = "cacertFile")]
23    pub cacert_file: Option<String>,
24    /// HTTPS certificate file path. Missing this to disable HTTPS.
25    #[serde(rename = "certFile")]
26    pub cert_file: Option<String>,
27    /// HTTPS private key file path. Missing this to disable HTTPS.
28    #[serde(rename = "keyFile")]
29    pub key_file: Option<String>,
30    /// Static file path.
31    #[serde(rename = "staticPath")]
32    pub static_path: Option<String>,
33}
34
35pub const DEF_HTTP_PORT: u16 = 1080;
36pub const DEF_HTTPS_PORT: u16 = 1443;
37
38/// To register Clap arguments.
39pub fn reg_args(cmd: Command) -> Command {
40    cmd.arg(
41        Arg::new("server.httpport")
42            .long("server.httpport")
43            .help("HTTP port")
44            .num_args(1)
45            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=65535)),
46    )
47    .arg(
48        Arg::new("server.httpsport")
49            .long("server.httpsport")
50            .help("HTTPS port")
51            .num_args(1)
52            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=65535)),
53    )
54    .arg(
55        Arg::new("server.cacertfile")
56            .long("server.cacertfile")
57            .help("HTTPS CA certificate file")
58            .num_args(1),
59    )
60    .arg(
61        Arg::new("server.certfile")
62            .long("server.certfile")
63            .help("HTTPS certificate file")
64            .num_args(1),
65    )
66    .arg(
67        Arg::new("server.keyfile")
68            .long("server.keyfile")
69            .help("HTTPS private key file")
70            .num_args(1),
71    )
72    .arg(
73        Arg::new("server.static")
74            .long("server.static")
75            .help("Static files directory path")
76            .num_args(1),
77    )
78}
79
80/// To read input arguments from command-line arguments and environment variables.
81///
82/// This function will call [`apply_default()`] to fill missing values so you do not need call it
83/// again.
84pub fn read_args(args: &ArgMatches) -> Config {
85    apply_default(&Config {
86        http_port: match args.get_one::<u64>("server.httpport") {
87            None => match env::var("SERVER_HTTP_PORT") {
88                Err(_) => Some(DEF_HTTP_PORT),
89                Ok(v) => match v.parse::<u16>() {
90                    Err(_) => Some(DEF_HTTP_PORT),
91                    Ok(v) => Some(v),
92                },
93            },
94            Some(v) => Some(*v as u16),
95        },
96        https_port: match args.get_one::<u64>("server.httpsport") {
97            None => match env::var("SERVER_HTTPS_PORT") {
98                Err(_) => Some(DEF_HTTPS_PORT),
99                Ok(v) => match v.parse::<u16>() {
100                    Err(_) => Some(DEF_HTTPS_PORT),
101                    Ok(v) => Some(v),
102                },
103            },
104            Some(v) => Some(*v as u16),
105        },
106        cacert_file: match args.get_one::<String>("server.cacertfile") {
107            None => match env::var("SERVER_CACERT_FILE") {
108                Err(_) => None,
109                Ok(v) => Some(v),
110            },
111            Some(v) => Some(v.clone()),
112        },
113        cert_file: match args.get_one::<String>("server.certfile") {
114            None => match env::var("SERVER_CERT_FILE") {
115                Err(_) => None,
116                Ok(v) => Some(v),
117            },
118            Some(v) => Some(v.clone()),
119        },
120        key_file: match args.get_one::<String>("server.keyfile") {
121            None => match env::var("SERVER_KEY_FILE") {
122                Err(_) => None,
123                Ok(v) => Some(v),
124            },
125            Some(v) => Some(v.clone()),
126        },
127        static_path: match args.get_one::<String>("server.static") {
128            None => match env::var("SERVER_STATIC_PATH") {
129                Err(_) => None,
130                Ok(v) => Some(v),
131            },
132            Some(v) => Some(v.clone()),
133        },
134    })
135}
136
137/// Fill missing configuration with default values.
138pub fn apply_default(config: &Config) -> Config {
139    Config {
140        http_port: match config.http_port {
141            None => Some(DEF_HTTP_PORT),
142            Some(v) => Some(v),
143        },
144        https_port: match config.https_port {
145            None => Some(DEF_HTTPS_PORT),
146            Some(v) => Some(v),
147        },
148        cacert_file: match config.cacert_file.as_ref() {
149            None => None,
150            Some(v) => Some(v.clone()),
151        },
152        cert_file: match config.cert_file.as_ref() {
153            None => None,
154            Some(v) => Some(v.clone()),
155        },
156        key_file: match config.key_file.as_ref() {
157            None => None,
158            Some(v) => Some(v.clone()),
159        },
160        static_path: match config.static_path.as_ref() {
161            None => None,
162            Some(v) => Some(v.clone()),
163        },
164    }
165}