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}