spikard 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +659 -659
- data/ext/spikard_rb/Cargo.toml +17 -17
- data/ext/spikard_rb/extconf.rb +10 -10
- data/ext/spikard_rb/src/lib.rs +6 -6
- data/lib/spikard/app.rb +386 -386
- data/lib/spikard/background.rb +27 -27
- data/lib/spikard/config.rb +396 -396
- data/lib/spikard/converters.rb +13 -13
- data/lib/spikard/handler_wrapper.rb +113 -113
- data/lib/spikard/provide.rb +214 -214
- data/lib/spikard/response.rb +173 -173
- data/lib/spikard/schema.rb +243 -243
- data/lib/spikard/sse.rb +111 -111
- data/lib/spikard/streaming_response.rb +44 -44
- data/lib/spikard/testing.rb +221 -221
- data/lib/spikard/upload_file.rb +131 -131
- data/lib/spikard/version.rb +5 -5
- data/lib/spikard/websocket.rb +59 -59
- data/lib/spikard.rb +43 -43
- data/sig/spikard.rbs +366 -360
- data/vendor/crates/spikard-core/Cargo.toml +40 -40
- data/vendor/crates/spikard-core/src/bindings/mod.rs +3 -3
- data/vendor/crates/spikard-core/src/bindings/response.rs +133 -133
- data/vendor/crates/spikard-core/src/debug.rs +63 -63
- data/vendor/crates/spikard-core/src/di/container.rs +726 -726
- data/vendor/crates/spikard-core/src/di/dependency.rs +273 -273
- data/vendor/crates/spikard-core/src/di/error.rs +118 -118
- data/vendor/crates/spikard-core/src/di/factory.rs +538 -538
- data/vendor/crates/spikard-core/src/di/graph.rs +545 -545
- data/vendor/crates/spikard-core/src/di/mod.rs +192 -192
- data/vendor/crates/spikard-core/src/di/resolved.rs +411 -411
- data/vendor/crates/spikard-core/src/di/value.rs +283 -283
- data/vendor/crates/spikard-core/src/errors.rs +39 -39
- data/vendor/crates/spikard-core/src/http.rs +153 -153
- data/vendor/crates/spikard-core/src/lib.rs +29 -29
- data/vendor/crates/spikard-core/src/lifecycle.rs +422 -422
- data/vendor/crates/spikard-core/src/parameters.rs +722 -722
- data/vendor/crates/spikard-core/src/problem.rs +310 -310
- data/vendor/crates/spikard-core/src/request_data.rs +189 -189
- data/vendor/crates/spikard-core/src/router.rs +249 -249
- data/vendor/crates/spikard-core/src/schema_registry.rs +183 -183
- data/vendor/crates/spikard-core/src/type_hints.rs +304 -304
- data/vendor/crates/spikard-core/src/validation.rs +699 -699
- data/vendor/crates/spikard-http/Cargo.toml +68 -68
- data/vendor/crates/spikard-http/src/auth.rs +247 -247
- data/vendor/crates/spikard-http/src/background.rs +249 -249
- data/vendor/crates/spikard-http/src/bindings/mod.rs +3 -3
- data/vendor/crates/spikard-http/src/bindings/response.rs +1 -1
- data/vendor/crates/spikard-http/src/body_metadata.rs +8 -8
- data/vendor/crates/spikard-http/src/cors.rs +490 -490
- data/vendor/crates/spikard-http/src/debug.rs +63 -63
- data/vendor/crates/spikard-http/src/di_handler.rs +423 -423
- data/vendor/crates/spikard-http/src/handler_response.rs +190 -190
- data/vendor/crates/spikard-http/src/handler_trait.rs +228 -228
- data/vendor/crates/spikard-http/src/handler_trait_tests.rs +284 -284
- data/vendor/crates/spikard-http/src/lib.rs +529 -529
- data/vendor/crates/spikard-http/src/lifecycle/adapter.rs +149 -149
- data/vendor/crates/spikard-http/src/lifecycle.rs +428 -428
- data/vendor/crates/spikard-http/src/middleware/mod.rs +285 -285
- data/vendor/crates/spikard-http/src/middleware/multipart.rs +86 -86
- data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +147 -147
- data/vendor/crates/spikard-http/src/middleware/validation.rs +287 -287
- data/vendor/crates/spikard-http/src/openapi/mod.rs +309 -309
- data/vendor/crates/spikard-http/src/openapi/parameter_extraction.rs +190 -190
- data/vendor/crates/spikard-http/src/openapi/schema_conversion.rs +308 -308
- data/vendor/crates/spikard-http/src/openapi/spec_generation.rs +195 -195
- data/vendor/crates/spikard-http/src/parameters.rs +1 -1
- data/vendor/crates/spikard-http/src/problem.rs +1 -1
- data/vendor/crates/spikard-http/src/query_parser.rs +369 -369
- data/vendor/crates/spikard-http/src/response.rs +399 -399
- data/vendor/crates/spikard-http/src/router.rs +1 -1
- data/vendor/crates/spikard-http/src/schema_registry.rs +1 -1
- data/vendor/crates/spikard-http/src/server/handler.rs +87 -87
- data/vendor/crates/spikard-http/src/server/lifecycle_execution.rs +98 -98
- data/vendor/crates/spikard-http/src/server/mod.rs +805 -805
- data/vendor/crates/spikard-http/src/server/request_extraction.rs +119 -119
- data/vendor/crates/spikard-http/src/sse.rs +447 -447
- data/vendor/crates/spikard-http/src/testing/form.rs +14 -14
- data/vendor/crates/spikard-http/src/testing/multipart.rs +60 -60
- data/vendor/crates/spikard-http/src/testing/test_client.rs +285 -285
- data/vendor/crates/spikard-http/src/testing.rs +377 -377
- data/vendor/crates/spikard-http/src/type_hints.rs +1 -1
- data/vendor/crates/spikard-http/src/validation.rs +1 -1
- data/vendor/crates/spikard-http/src/websocket.rs +324 -324
- data/vendor/crates/spikard-rb/Cargo.toml +42 -42
- data/vendor/crates/spikard-rb/build.rs +8 -8
- data/vendor/crates/spikard-rb/src/background.rs +63 -63
- data/vendor/crates/spikard-rb/src/config.rs +294 -294
- data/vendor/crates/spikard-rb/src/conversion.rs +453 -453
- data/vendor/crates/spikard-rb/src/di.rs +409 -409
- data/vendor/crates/spikard-rb/src/handler.rs +625 -625
- data/vendor/crates/spikard-rb/src/lib.rs +2771 -2771
- data/vendor/crates/spikard-rb/src/lifecycle.rs +274 -274
- data/vendor/crates/spikard-rb/src/server.rs +283 -283
- data/vendor/crates/spikard-rb/src/sse.rs +231 -231
- data/vendor/crates/spikard-rb/src/test_client.rs +404 -404
- data/vendor/crates/spikard-rb/src/test_sse.rs +143 -143
- data/vendor/crates/spikard-rb/src/test_websocket.rs +221 -221
- data/vendor/crates/spikard-rb/src/websocket.rs +233 -233
- metadata +1 -1
|
@@ -1,195 +1,195 @@
|
|
|
1
|
-
//! OpenAPI specification generation and assembly
|
|
2
|
-
|
|
3
|
-
use crate::RouteMetadata;
|
|
4
|
-
use utoipa::openapi::HttpMethod;
|
|
5
|
-
use utoipa::openapi::security::SecurityScheme;
|
|
6
|
-
use utoipa::openapi::{Components, Info, OpenApi, OpenApiBuilder, PathItem, Paths, RefOr, Response, Responses};
|
|
7
|
-
|
|
8
|
-
/// Convert route to OpenAPI PathItem
|
|
9
|
-
fn route_to_path_item(route: &RouteMetadata) -> Result<PathItem, String> {
|
|
10
|
-
let operation = route_to_operation(route)?;
|
|
11
|
-
|
|
12
|
-
let http_method = match route.method.to_uppercase().as_str() {
|
|
13
|
-
"GET" => HttpMethod::Get,
|
|
14
|
-
"POST" => HttpMethod::Post,
|
|
15
|
-
"PUT" => HttpMethod::Put,
|
|
16
|
-
"DELETE" => HttpMethod::Delete,
|
|
17
|
-
"PATCH" => HttpMethod::Patch,
|
|
18
|
-
"HEAD" => HttpMethod::Head,
|
|
19
|
-
"OPTIONS" => HttpMethod::Options,
|
|
20
|
-
_ => return Err(format!("Unsupported HTTP method: {}", route.method)),
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
let path_item = PathItem::new(http_method, operation);
|
|
24
|
-
|
|
25
|
-
Ok(path_item)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/// Convert route to OpenAPI Operation
|
|
29
|
-
fn route_to_operation(route: &RouteMetadata) -> Result<utoipa::openapi::path::Operation, String> {
|
|
30
|
-
let mut operation = utoipa::openapi::path::Operation::new();
|
|
31
|
-
|
|
32
|
-
if let Some(param_schema) = &route.parameter_schema {
|
|
33
|
-
let parameters =
|
|
34
|
-
crate::openapi::parameter_extraction::extract_parameters_from_schema(param_schema, &route.path)?;
|
|
35
|
-
if !parameters.is_empty() {
|
|
36
|
-
let unwrapped: Vec<_> = parameters
|
|
37
|
-
.into_iter()
|
|
38
|
-
.filter_map(|p| if let RefOr::T(param) = p { Some(param) } else { None })
|
|
39
|
-
.collect();
|
|
40
|
-
operation.parameters = Some(unwrapped);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if let Some(request_schema) = &route.request_schema {
|
|
45
|
-
let request_body = crate::openapi::schema_conversion::json_schema_to_request_body(request_schema)?;
|
|
46
|
-
operation.request_body = Some(request_body);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
let mut responses = Responses::new();
|
|
50
|
-
if let Some(response_schema) = &route.response_schema {
|
|
51
|
-
let response = crate::openapi::schema_conversion::json_schema_to_response(response_schema)?;
|
|
52
|
-
responses.responses.insert("200".to_string(), RefOr::T(response));
|
|
53
|
-
} else {
|
|
54
|
-
responses
|
|
55
|
-
.responses
|
|
56
|
-
.insert("200".to_string(), RefOr::T(Response::new("Successful response")));
|
|
57
|
-
}
|
|
58
|
-
operation.responses = responses;
|
|
59
|
-
|
|
60
|
-
Ok(operation)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/// Assemble OpenAPI specification from routes with auto-detection of security schemes
|
|
64
|
-
pub fn assemble_openapi_spec(
|
|
65
|
-
routes: &[RouteMetadata],
|
|
66
|
-
config: &super::OpenApiConfig,
|
|
67
|
-
server_config: Option<&crate::ServerConfig>,
|
|
68
|
-
) -> Result<OpenApi, String> {
|
|
69
|
-
let mut info = Info::new(&config.title, &config.version);
|
|
70
|
-
if let Some(desc) = &config.description {
|
|
71
|
-
info.description = Some(desc.clone());
|
|
72
|
-
}
|
|
73
|
-
if let Some(contact_info) = &config.contact {
|
|
74
|
-
let mut contact = utoipa::openapi::Contact::default();
|
|
75
|
-
if let Some(name) = &contact_info.name {
|
|
76
|
-
contact.name = Some(name.clone());
|
|
77
|
-
}
|
|
78
|
-
if let Some(email) = &contact_info.email {
|
|
79
|
-
contact.email = Some(email.clone());
|
|
80
|
-
}
|
|
81
|
-
if let Some(url) = &contact_info.url {
|
|
82
|
-
contact.url = Some(url.clone());
|
|
83
|
-
}
|
|
84
|
-
info.contact = Some(contact);
|
|
85
|
-
}
|
|
86
|
-
if let Some(license_info) = &config.license {
|
|
87
|
-
let mut license = utoipa::openapi::License::new(&license_info.name);
|
|
88
|
-
if let Some(url) = &license_info.url {
|
|
89
|
-
license.url = Some(url.clone());
|
|
90
|
-
}
|
|
91
|
-
info.license = Some(license);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
let servers = if config.servers.is_empty() {
|
|
95
|
-
None
|
|
96
|
-
} else {
|
|
97
|
-
Some(
|
|
98
|
-
config
|
|
99
|
-
.servers
|
|
100
|
-
.iter()
|
|
101
|
-
.map(|s| {
|
|
102
|
-
let mut server = utoipa::openapi::Server::new(&s.url);
|
|
103
|
-
if let Some(desc) = &s.description {
|
|
104
|
-
server.description = Some(desc.clone());
|
|
105
|
-
}
|
|
106
|
-
server
|
|
107
|
-
})
|
|
108
|
-
.collect(),
|
|
109
|
-
)
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
let mut paths = Paths::new();
|
|
113
|
-
for route in routes {
|
|
114
|
-
let path_item = route_to_path_item(route)?;
|
|
115
|
-
paths.paths.insert(route.path.clone(), path_item);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
let mut components = Components::new();
|
|
119
|
-
let mut global_security = Vec::new();
|
|
120
|
-
|
|
121
|
-
if let Some(server_cfg) = server_config {
|
|
122
|
-
if let Some(_jwt_cfg) = &server_cfg.jwt_auth {
|
|
123
|
-
let jwt_scheme = SecurityScheme::Http(
|
|
124
|
-
utoipa::openapi::security::HttpBuilder::new()
|
|
125
|
-
.scheme(utoipa::openapi::security::HttpAuthScheme::Bearer)
|
|
126
|
-
.bearer_format("JWT")
|
|
127
|
-
.build(),
|
|
128
|
-
);
|
|
129
|
-
components.add_security_scheme("bearerAuth", jwt_scheme);
|
|
130
|
-
|
|
131
|
-
let security_req = utoipa::openapi::security::SecurityRequirement::new("bearerAuth", Vec::<String>::new());
|
|
132
|
-
global_security.push(security_req);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if let Some(api_key_cfg) = &server_cfg.api_key_auth {
|
|
136
|
-
use utoipa::openapi::security::ApiKey;
|
|
137
|
-
let api_key_scheme = SecurityScheme::ApiKey(ApiKey::Header(utoipa::openapi::security::ApiKeyValue::new(
|
|
138
|
-
&api_key_cfg.header_name,
|
|
139
|
-
)));
|
|
140
|
-
components.add_security_scheme("apiKeyAuth", api_key_scheme);
|
|
141
|
-
|
|
142
|
-
let security_req = utoipa::openapi::security::SecurityRequirement::new("apiKeyAuth", Vec::<String>::new());
|
|
143
|
-
global_security.push(security_req);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if !config.security_schemes.is_empty() {
|
|
148
|
-
for (name, scheme_info) in &config.security_schemes {
|
|
149
|
-
let scheme = crate::openapi::security_scheme_info_to_openapi(scheme_info);
|
|
150
|
-
components.add_security_scheme(name, scheme);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
let mut openapi = OpenApiBuilder::new()
|
|
155
|
-
.info(info)
|
|
156
|
-
.paths(paths)
|
|
157
|
-
.components(Some(components))
|
|
158
|
-
.build();
|
|
159
|
-
|
|
160
|
-
if let Some(servers) = servers {
|
|
161
|
-
openapi.servers = Some(servers);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if !global_security.is_empty() {
|
|
165
|
-
openapi.security = Some(global_security);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
Ok(openapi)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
#[cfg(test)]
|
|
172
|
-
mod tests {
|
|
173
|
-
use super::*;
|
|
174
|
-
|
|
175
|
-
#[test]
|
|
176
|
-
fn test_route_to_path_item_get() {
|
|
177
|
-
let route = RouteMetadata {
|
|
178
|
-
method: "GET".to_string(),
|
|
179
|
-
path: "/users".to_string(),
|
|
180
|
-
handler_name: "list_users".to_string(),
|
|
181
|
-
request_schema: None,
|
|
182
|
-
response_schema: None,
|
|
183
|
-
parameter_schema: None,
|
|
184
|
-
file_params: None,
|
|
185
|
-
is_async: true,
|
|
186
|
-
cors: None,
|
|
187
|
-
body_param_name: None,
|
|
188
|
-
#[cfg(feature = "di")]
|
|
189
|
-
handler_dependencies: None,
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
let result = route_to_path_item(&route);
|
|
193
|
-
assert!(result.is_ok());
|
|
194
|
-
}
|
|
195
|
-
}
|
|
1
|
+
//! OpenAPI specification generation and assembly
|
|
2
|
+
|
|
3
|
+
use crate::RouteMetadata;
|
|
4
|
+
use utoipa::openapi::HttpMethod;
|
|
5
|
+
use utoipa::openapi::security::SecurityScheme;
|
|
6
|
+
use utoipa::openapi::{Components, Info, OpenApi, OpenApiBuilder, PathItem, Paths, RefOr, Response, Responses};
|
|
7
|
+
|
|
8
|
+
/// Convert route to OpenAPI PathItem
|
|
9
|
+
fn route_to_path_item(route: &RouteMetadata) -> Result<PathItem, String> {
|
|
10
|
+
let operation = route_to_operation(route)?;
|
|
11
|
+
|
|
12
|
+
let http_method = match route.method.to_uppercase().as_str() {
|
|
13
|
+
"GET" => HttpMethod::Get,
|
|
14
|
+
"POST" => HttpMethod::Post,
|
|
15
|
+
"PUT" => HttpMethod::Put,
|
|
16
|
+
"DELETE" => HttpMethod::Delete,
|
|
17
|
+
"PATCH" => HttpMethod::Patch,
|
|
18
|
+
"HEAD" => HttpMethod::Head,
|
|
19
|
+
"OPTIONS" => HttpMethod::Options,
|
|
20
|
+
_ => return Err(format!("Unsupported HTTP method: {}", route.method)),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
let path_item = PathItem::new(http_method, operation);
|
|
24
|
+
|
|
25
|
+
Ok(path_item)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Convert route to OpenAPI Operation
|
|
29
|
+
fn route_to_operation(route: &RouteMetadata) -> Result<utoipa::openapi::path::Operation, String> {
|
|
30
|
+
let mut operation = utoipa::openapi::path::Operation::new();
|
|
31
|
+
|
|
32
|
+
if let Some(param_schema) = &route.parameter_schema {
|
|
33
|
+
let parameters =
|
|
34
|
+
crate::openapi::parameter_extraction::extract_parameters_from_schema(param_schema, &route.path)?;
|
|
35
|
+
if !parameters.is_empty() {
|
|
36
|
+
let unwrapped: Vec<_> = parameters
|
|
37
|
+
.into_iter()
|
|
38
|
+
.filter_map(|p| if let RefOr::T(param) = p { Some(param) } else { None })
|
|
39
|
+
.collect();
|
|
40
|
+
operation.parameters = Some(unwrapped);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if let Some(request_schema) = &route.request_schema {
|
|
45
|
+
let request_body = crate::openapi::schema_conversion::json_schema_to_request_body(request_schema)?;
|
|
46
|
+
operation.request_body = Some(request_body);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let mut responses = Responses::new();
|
|
50
|
+
if let Some(response_schema) = &route.response_schema {
|
|
51
|
+
let response = crate::openapi::schema_conversion::json_schema_to_response(response_schema)?;
|
|
52
|
+
responses.responses.insert("200".to_string(), RefOr::T(response));
|
|
53
|
+
} else {
|
|
54
|
+
responses
|
|
55
|
+
.responses
|
|
56
|
+
.insert("200".to_string(), RefOr::T(Response::new("Successful response")));
|
|
57
|
+
}
|
|
58
|
+
operation.responses = responses;
|
|
59
|
+
|
|
60
|
+
Ok(operation)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Assemble OpenAPI specification from routes with auto-detection of security schemes
|
|
64
|
+
pub fn assemble_openapi_spec(
|
|
65
|
+
routes: &[RouteMetadata],
|
|
66
|
+
config: &super::OpenApiConfig,
|
|
67
|
+
server_config: Option<&crate::ServerConfig>,
|
|
68
|
+
) -> Result<OpenApi, String> {
|
|
69
|
+
let mut info = Info::new(&config.title, &config.version);
|
|
70
|
+
if let Some(desc) = &config.description {
|
|
71
|
+
info.description = Some(desc.clone());
|
|
72
|
+
}
|
|
73
|
+
if let Some(contact_info) = &config.contact {
|
|
74
|
+
let mut contact = utoipa::openapi::Contact::default();
|
|
75
|
+
if let Some(name) = &contact_info.name {
|
|
76
|
+
contact.name = Some(name.clone());
|
|
77
|
+
}
|
|
78
|
+
if let Some(email) = &contact_info.email {
|
|
79
|
+
contact.email = Some(email.clone());
|
|
80
|
+
}
|
|
81
|
+
if let Some(url) = &contact_info.url {
|
|
82
|
+
contact.url = Some(url.clone());
|
|
83
|
+
}
|
|
84
|
+
info.contact = Some(contact);
|
|
85
|
+
}
|
|
86
|
+
if let Some(license_info) = &config.license {
|
|
87
|
+
let mut license = utoipa::openapi::License::new(&license_info.name);
|
|
88
|
+
if let Some(url) = &license_info.url {
|
|
89
|
+
license.url = Some(url.clone());
|
|
90
|
+
}
|
|
91
|
+
info.license = Some(license);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let servers = if config.servers.is_empty() {
|
|
95
|
+
None
|
|
96
|
+
} else {
|
|
97
|
+
Some(
|
|
98
|
+
config
|
|
99
|
+
.servers
|
|
100
|
+
.iter()
|
|
101
|
+
.map(|s| {
|
|
102
|
+
let mut server = utoipa::openapi::Server::new(&s.url);
|
|
103
|
+
if let Some(desc) = &s.description {
|
|
104
|
+
server.description = Some(desc.clone());
|
|
105
|
+
}
|
|
106
|
+
server
|
|
107
|
+
})
|
|
108
|
+
.collect(),
|
|
109
|
+
)
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
let mut paths = Paths::new();
|
|
113
|
+
for route in routes {
|
|
114
|
+
let path_item = route_to_path_item(route)?;
|
|
115
|
+
paths.paths.insert(route.path.clone(), path_item);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
let mut components = Components::new();
|
|
119
|
+
let mut global_security = Vec::new();
|
|
120
|
+
|
|
121
|
+
if let Some(server_cfg) = server_config {
|
|
122
|
+
if let Some(_jwt_cfg) = &server_cfg.jwt_auth {
|
|
123
|
+
let jwt_scheme = SecurityScheme::Http(
|
|
124
|
+
utoipa::openapi::security::HttpBuilder::new()
|
|
125
|
+
.scheme(utoipa::openapi::security::HttpAuthScheme::Bearer)
|
|
126
|
+
.bearer_format("JWT")
|
|
127
|
+
.build(),
|
|
128
|
+
);
|
|
129
|
+
components.add_security_scheme("bearerAuth", jwt_scheme);
|
|
130
|
+
|
|
131
|
+
let security_req = utoipa::openapi::security::SecurityRequirement::new("bearerAuth", Vec::<String>::new());
|
|
132
|
+
global_security.push(security_req);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if let Some(api_key_cfg) = &server_cfg.api_key_auth {
|
|
136
|
+
use utoipa::openapi::security::ApiKey;
|
|
137
|
+
let api_key_scheme = SecurityScheme::ApiKey(ApiKey::Header(utoipa::openapi::security::ApiKeyValue::new(
|
|
138
|
+
&api_key_cfg.header_name,
|
|
139
|
+
)));
|
|
140
|
+
components.add_security_scheme("apiKeyAuth", api_key_scheme);
|
|
141
|
+
|
|
142
|
+
let security_req = utoipa::openapi::security::SecurityRequirement::new("apiKeyAuth", Vec::<String>::new());
|
|
143
|
+
global_security.push(security_req);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if !config.security_schemes.is_empty() {
|
|
148
|
+
for (name, scheme_info) in &config.security_schemes {
|
|
149
|
+
let scheme = crate::openapi::security_scheme_info_to_openapi(scheme_info);
|
|
150
|
+
components.add_security_scheme(name, scheme);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let mut openapi = OpenApiBuilder::new()
|
|
155
|
+
.info(info)
|
|
156
|
+
.paths(paths)
|
|
157
|
+
.components(Some(components))
|
|
158
|
+
.build();
|
|
159
|
+
|
|
160
|
+
if let Some(servers) = servers {
|
|
161
|
+
openapi.servers = Some(servers);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if !global_security.is_empty() {
|
|
165
|
+
openapi.security = Some(global_security);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
Ok(openapi)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
#[cfg(test)]
|
|
172
|
+
mod tests {
|
|
173
|
+
use super::*;
|
|
174
|
+
|
|
175
|
+
#[test]
|
|
176
|
+
fn test_route_to_path_item_get() {
|
|
177
|
+
let route = RouteMetadata {
|
|
178
|
+
method: "GET".to_string(),
|
|
179
|
+
path: "/users".to_string(),
|
|
180
|
+
handler_name: "list_users".to_string(),
|
|
181
|
+
request_schema: None,
|
|
182
|
+
response_schema: None,
|
|
183
|
+
parameter_schema: None,
|
|
184
|
+
file_params: None,
|
|
185
|
+
is_async: true,
|
|
186
|
+
cors: None,
|
|
187
|
+
body_param_name: None,
|
|
188
|
+
#[cfg(feature = "di")]
|
|
189
|
+
handler_dependencies: None,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
let result = route_to_path_item(&route);
|
|
193
|
+
assert!(result.is_ok());
|
|
194
|
+
}
|
|
195
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
pub use spikard_core::parameters::*;
|
|
1
|
+
pub use spikard_core::parameters::*;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
pub use spikard_core::problem::*;
|
|
1
|
+
pub use spikard_core::problem::*;
|