swagger_ui/
lib.rs

1use rust_embed::RustEmbed;
2use serde::{Deserialize, Serialize};
3
4/// Assets from swagger-ui-dist
5#[derive(RustEmbed)]
6#[folder = "./dist/"]
7pub struct Assets;
8
9/// Contains a named url.
10#[derive(Debug, Clone, Deserialize, Serialize)]
11pub struct UrlObject {
12    /// The name of the url.
13    pub name: String,
14    /// The url itself.
15    pub url: String,
16}
17
18impl UrlObject {
19    /// Create a new `UrlObject` from the provided name and url.
20    pub fn new(name: &str, url: &str) -> Self {
21        Self {
22            name: name.to_string(),
23            url: url.to_string(),
24        }
25    }
26}
27
28/// Used to control the way models are displayed by default.
29#[derive(Debug, Clone, Serialize, Deserialize)]
30#[serde(rename_all = "camelCase")]
31pub enum DefaultModelRendering {
32    /// Expand the `example` section.
33    Example,
34    /// Expand the `model` section.
35    Model,
36}
37
38/// Used to control the default expansion setting for the operations and tags.
39#[derive(Debug, Clone, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub enum DocExpansion {
42    /// Expands only the tags.
43    List,
44    /// Expands the tags and operations
45    Full,
46    /// Expands nothing
47    None,
48}
49
50/// Used to enable, disable and preconfigure filtering
51#[derive(Debug, Clone, Serialize, Deserialize)]
52#[serde(untagged)]
53pub enum Filter {
54    /// Use this variant to enable or disable filtering.
55    Bool(bool),
56    /// Use this variant to enable filtering, and preconfigure a filter.
57    Str(String),
58}
59
60/// Used to represent openapi specification file
61pub struct Spec {
62    /// Spec file name
63    pub name: String,
64    /// Spec file content
65    pub content: &'static [u8]
66}
67
68/// Macro used to create `Spec` struct,
69/// loads file using `include_bytes!`
70#[macro_export]
71macro_rules! swagger_spec_file {
72    ($name: literal) => {
73        swagger_ui::Spec {
74            name: $name.to_string(),
75            content: include_bytes!($name)
76        }
77    };
78}
79
80/// Swagger UI configuration
81#[derive(Debug, Clone, Serialize, Deserialize)]
82#[serde(rename_all = "camelCase")]
83pub struct Config {
84    /// The url to a single `openapi.json` file that is showed when the web ui is first opened.
85    #[serde(default, skip_serializing_if = "String::is_empty")]
86    pub url: String,
87    /// A list of named urls that contain all the `openapi.json` files that you want to display in
88    /// your web ui. If this field is populated, the `url` field is not used.
89    #[serde(default, skip_serializing_if = "Vec::is_empty")]
90    pub urls: Vec<UrlObject>,
91
92    // display options:
93    /// If set to true, enables deep linking for tags and operations. See the
94    /// [Deep Linking documentation](https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/deep-linking.md)
95    /// for more information.
96    /// Default: `false`.
97    pub deep_linking: bool,
98    /// Controls the display of operationId in operations list.
99    /// Default: `false`.
100    pub display_operation_id: bool,
101    /// The default expansion depth for models (set to -1 completely hide the models).
102    /// Default: `1`.
103    pub default_models_expand_depth: i32,
104    /// The default expansion depth for the model on the model-example section.
105    /// Default: `1`.
106    pub default_model_expand_depth: i32,
107    /// Controls how the model is shown when the API is first rendered. (The user can always switch
108    /// the rendering for a given model by clicking the 'Model' and 'Example Value' links.)
109    /// Default: `DefaultModelRendering::Example`.
110    pub default_model_rendering: DefaultModelRendering,
111    /// Controls the display of the request duration (in milliseconds) for "Try it out" requests.
112    /// Default: `false`.
113    pub display_request_duration: bool,
114    /// Controls the default expansion setting for the operations and tags.
115    /// Default: `DocExpansion::List`.
116    pub doc_expansion: DocExpansion,
117    /// If set, enables filtering. The top bar will show an edit box that you can use to filter the
118    /// tagged operations that are shown. Filtering is case sensitive matching the filter expression
119    /// anywhere inside the tag.
120    /// Default: `Filter(false)`.
121    pub filter: Filter,
122    /// If set, limits the number of tagged operations displayed to at most this many. The default
123    /// is to show all operations.
124    /// Default: `None` (displays all tagged operations).
125    #[serde(default, skip_serializing_if = "is_zero")]
126    pub max_displayed_tags: u32,
127    /// Controls the display of vendor extension (`x-`) fields and values for Operations,
128    /// Parameters, and Schema.
129    /// Default: `false`.
130    pub show_extensions: bool,
131    /// Controls the display of extensions (`pattern`, `maxLength`, `minLength`, `maximum`,
132    /// `minimum`) fields and values for Parameters.
133    /// Default: `false`.
134    pub show_common_extensions: bool,
135}
136
137fn is_zero(num: &u32) -> bool {
138    *num == 0
139}
140
141impl Default for Config {
142    fn default() -> Self {
143        Self {
144            url: String::new(),
145            urls: vec![],
146            deep_linking: false,
147            display_operation_id: false,
148            default_model_expand_depth: 1,
149            default_model_rendering: DefaultModelRendering::Example,
150            default_models_expand_depth: 1,
151            display_request_duration: false,
152            doc_expansion: DocExpansion::List,
153            filter: Filter::Bool(false),
154            max_displayed_tags: 0,
155            show_extensions: false,
156            show_common_extensions: false,
157        }
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use std::path::Path;
164    use crate::Assets;
165
166    fn asset_list() -> [&'static str; 8] {
167        [
168            "favicon-16x16.png",
169            "favicon-32x32.png",
170            "index.html",
171            "oauth2-redirect.html",
172            "swagger-ui.css",
173            "swagger-ui.js",
174            "swagger-ui-bundle.js",
175            "swagger-ui-standalone-preset.js",
176        ]
177    }
178
179    #[test]
180    fn swagger_ui_dist_exists() {
181        println!("Checking if assets exists");
182        for file in &asset_list() {
183            let asset = format!("dist/{}", file);
184            println!("\t{}", asset);
185            assert!(Path::new(&asset).exists());
186        }
187    }
188
189    #[test]
190    fn swagger_ui_assets() {
191        println!("Checking if assets exists in binary");
192        for asset in &asset_list() {
193            println!("\t{}", asset);
194            let data = Assets::get(&asset).unwrap();
195            assert!(!data.is_empty());
196        }
197    }
198}