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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use schemars::JsonSchema;
use serde::Deserialize;
use spring::config::Configurable;
use std::net::{IpAddr, Ipv4Addr};

/// spring-web Config
#[derive(Debug, Configurable, JsonSchema, Deserialize)]
#[config_prefix = "web"]
pub struct WebConfig {
    #[serde(default = "default_binding")]
    pub(crate) binding: IpAddr,
    #[serde(default = "default_port")]
    pub(crate) port: u16,
    pub(crate) middlewares: Option<Middlewares>,
}

fn default_binding() -> IpAddr {
    IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))
}

fn default_port() -> u16 {
    8080
}

/// Server middleware configuration structure.
#[derive(Debug, Clone, JsonSchema, Deserialize)]
pub struct Middlewares {
    /// Middleware that enable compression for the response.
    pub compression: Option<EnableMiddleware>,
    /// Middleware that limit the payload request.
    pub limit_payload: Option<LimitPayloadMiddleware>,
    /// Middleware that improve the tracing logger and adding trace id for each
    /// request.
    pub logger: Option<EnableMiddleware>,
    /// catch any code panic and log the error.
    pub catch_panic: Option<EnableMiddleware>,
    /// Setting a global timeout for the requests
    pub timeout_request: Option<TimeoutRequestMiddleware>,
    /// Setting cors configuration
    pub cors: Option<CorsMiddleware>,
    /// Serving static assets
    #[serde(rename = "static")]
    pub static_assets: Option<StaticAssetsMiddleware>,
}

/// Static asset middleware configuration
#[derive(Debug, Clone, JsonSchema, Deserialize)]
pub struct StaticAssetsMiddleware {
    /// toggle enable
    pub enable: bool,
    /// Check that assets must exist on disk
    #[serde(default = "bool::default")]
    pub must_exist: bool,
    /// Fallback page for a case when no asset exists (404). Useful for SPA
    /// (single page app) where routes are virtual.
    #[serde(default = "default_fallback")]
    pub fallback: String,
    /// Enable `precompressed_gzip`
    #[serde(default = "bool::default")]
    pub precompressed: bool,
    /// Uri for the assets
    #[serde(default = "default_assets_uri")]
    pub uri: String,
    /// Path for the assets
    #[serde(default = "default_assets_path")]
    pub path: String,
}

/// CORS middleware configuration
#[derive(Debug, Clone, JsonSchema, Deserialize)]
pub struct CorsMiddleware {
    /// toggle enable
    pub enable: bool,
    /// Allow origins
    pub allow_origins: Option<Vec<String>>,
    /// Allow headers
    pub allow_headers: Option<Vec<String>>,
    /// Allow methods
    pub allow_methods: Option<Vec<String>>,
    /// Max age
    pub max_age: Option<u64>,
}

/// Timeout middleware configuration
#[derive(Debug, Clone, JsonSchema, Deserialize)]
pub struct TimeoutRequestMiddleware {
    /// toggle enable
    pub enable: bool,
    /// Timeout request in milliseconds
    pub timeout: u64,
}

/// Limit payload size middleware configuration
#[derive(Debug, Clone, JsonSchema, Deserialize)]
pub struct LimitPayloadMiddleware {
    /// toggle enable
    pub enable: bool,
    /// Body limit. for example: 5mb
    pub body_limit: String,
}

/// A generic middleware configuration that can be enabled or
/// disabled.
#[derive(Debug, PartialEq, Clone, JsonSchema, Deserialize)]
pub struct EnableMiddleware {
    /// toggle enable
    pub enable: bool,
}

fn default_assets_path() -> String {
    "static".to_string()
}

fn default_assets_uri() -> String {
    "/static".to_string()
}

fn default_fallback() -> String {
    "index.html".to_string()
}