spring_web/
config.rs

1use schemars::JsonSchema;
2use serde::Deserialize;
3use spring::config::Configurable;
4use std::net::{IpAddr, Ipv4Addr};
5use tracing::Level;
6
7/// spring-web Config
8#[derive(Debug, Configurable, JsonSchema, Deserialize)]
9#[config_prefix = "web"]
10pub struct WebConfig {
11    #[serde(flatten)]
12    pub(crate) server: ServerConfig,
13    pub(crate) middlewares: Option<Middlewares>,
14}
15
16#[derive(Debug, Clone, JsonSchema, Deserialize)]
17pub struct ServerConfig {
18    #[serde(default = "default_binding")]
19    pub(crate) binding: IpAddr,
20    #[serde(default = "default_port")]
21    pub(crate) port: u16,
22    #[serde(default)]
23    pub(crate) connect_info: bool,
24    #[serde(default)]
25    pub(crate) graceful: bool,
26}
27
28fn default_binding() -> IpAddr {
29    IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))
30}
31
32fn default_port() -> u16 {
33    8080
34}
35
36/// Server middleware configuration structure.
37#[derive(Debug, Clone, JsonSchema, Deserialize)]
38pub struct Middlewares {
39    /// Middleware that enable compression for the response.
40    pub compression: Option<EnableMiddleware>,
41    /// Middleware that limit the payload request.
42    pub limit_payload: Option<LimitPayloadMiddleware>,
43    /// Middleware that improve the tracing logger and adding trace id for each
44    /// request.
45    pub logger: Option<TraceLoggerMiddleware>,
46    /// catch any code panic and log the error.
47    pub catch_panic: Option<EnableMiddleware>,
48    /// Setting a global timeout for the requests
49    pub timeout_request: Option<TimeoutRequestMiddleware>,
50    /// Setting cors configuration
51    pub cors: Option<CorsMiddleware>,
52    /// Serving static assets
53    #[serde(rename = "static")]
54    pub static_assets: Option<StaticAssetsMiddleware>,
55}
56
57/// Static asset middleware configuration
58#[derive(Debug, Clone, JsonSchema, Deserialize)]
59pub struct StaticAssetsMiddleware {
60    /// toggle enable
61    pub enable: bool,
62    /// Check that assets must exist on disk
63    #[serde(default = "bool::default")]
64    pub must_exist: bool,
65    /// Fallback page for a case when no asset exists (404). Useful for SPA
66    /// (single page app) where routes are virtual.
67    #[serde(default = "default_fallback")]
68    pub fallback: String,
69    /// Enable `precompressed_gzip`
70    #[serde(default = "bool::default")]
71    pub precompressed: bool,
72    /// Uri for the assets
73    #[serde(default = "default_assets_uri")]
74    pub uri: String,
75    /// Path for the assets
76    #[serde(default = "default_assets_path")]
77    pub path: String,
78}
79
80/// CORS middleware configuration
81#[derive(Debug, Clone, JsonSchema, Deserialize)]
82pub struct TraceLoggerMiddleware {
83    /// toggle enable
84    pub enable: bool,
85    pub level: LogLevel,
86}
87
88#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]
89pub enum LogLevel {
90    /// The "trace" level.
91    #[serde(rename = "trace")]
92    Trace,
93    /// The "debug" level.
94    #[serde(rename = "debug")]
95    Debug,
96    /// The "info" level.
97    #[serde(rename = "info")]
98    #[default]
99    Info,
100    /// The "warn" level.
101    #[serde(rename = "warn")]
102    Warn,
103    /// The "error" level.
104    #[serde(rename = "error")]
105    Error,
106}
107
108#[allow(clippy::from_over_into)]
109impl Into<Level> for LogLevel {
110    fn into(self) -> Level {
111        match self {
112            Self::Trace => Level::TRACE,
113            Self::Debug => Level::DEBUG,
114            Self::Info => Level::INFO,
115            Self::Warn => Level::WARN,
116            Self::Error => Level::ERROR,
117        }
118    }
119}
120
121/// CORS middleware configuration
122#[derive(Debug, Clone, JsonSchema, Deserialize)]
123pub struct CorsMiddleware {
124    /// toggle enable
125    pub enable: bool,
126    /// Allow origins
127    pub allow_origins: Option<Vec<String>>,
128    /// Allow headers
129    pub allow_headers: Option<Vec<String>>,
130    /// Allow methods
131    pub allow_methods: Option<Vec<String>>,
132    /// Max age
133    pub max_age: Option<u64>,
134}
135
136/// Timeout middleware configuration
137#[derive(Debug, Clone, JsonSchema, Deserialize)]
138pub struct TimeoutRequestMiddleware {
139    /// toggle enable
140    pub enable: bool,
141    /// Timeout request in milliseconds
142    pub timeout: u64,
143}
144
145/// Limit payload size middleware configuration
146#[derive(Debug, Clone, JsonSchema, Deserialize)]
147pub struct LimitPayloadMiddleware {
148    /// toggle enable
149    pub enable: bool,
150    /// Body limit. for example: 5mb
151    pub body_limit: String,
152}
153
154/// A generic middleware configuration that can be enabled or
155/// disabled.
156#[derive(Debug, PartialEq, Clone, JsonSchema, Deserialize)]
157pub struct EnableMiddleware {
158    /// toggle enable
159    pub enable: bool,
160}
161
162fn default_assets_path() -> String {
163    "static".to_string()
164}
165
166fn default_assets_uri() -> String {
167    "/static".to_string()
168}
169
170fn default_fallback() -> String {
171    "index.html".to_string()
172}