spikard 0.2.5 → 0.3.1

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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +659 -626
  4. data/ext/spikard_rb/Cargo.toml +17 -17
  5. data/ext/spikard_rb/extconf.rb +10 -10
  6. data/ext/spikard_rb/src/lib.rs +6 -6
  7. data/lib/spikard/app.rb +386 -374
  8. data/lib/spikard/background.rb +27 -27
  9. data/lib/spikard/config.rb +396 -396
  10. data/lib/spikard/converters.rb +13 -85
  11. data/lib/spikard/handler_wrapper.rb +113 -116
  12. data/lib/spikard/provide.rb +214 -228
  13. data/lib/spikard/response.rb +173 -109
  14. data/lib/spikard/schema.rb +243 -243
  15. data/lib/spikard/sse.rb +111 -111
  16. data/lib/spikard/streaming_response.rb +44 -21
  17. data/lib/spikard/testing.rb +221 -221
  18. data/lib/spikard/upload_file.rb +131 -131
  19. data/lib/spikard/version.rb +5 -5
  20. data/lib/spikard/websocket.rb +59 -59
  21. data/lib/spikard.rb +43 -43
  22. data/sig/spikard.rbs +360 -349
  23. data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.10.0/build/buildkitd.toml +2 -0
  24. metadata +5 -85
  25. data/vendor/crates/spikard-core/Cargo.toml +0 -40
  26. data/vendor/crates/spikard-core/src/bindings/mod.rs +0 -3
  27. data/vendor/crates/spikard-core/src/bindings/response.rs +0 -133
  28. data/vendor/crates/spikard-core/src/debug.rs +0 -63
  29. data/vendor/crates/spikard-core/src/di/container.rs +0 -726
  30. data/vendor/crates/spikard-core/src/di/dependency.rs +0 -273
  31. data/vendor/crates/spikard-core/src/di/error.rs +0 -118
  32. data/vendor/crates/spikard-core/src/di/factory.rs +0 -538
  33. data/vendor/crates/spikard-core/src/di/graph.rs +0 -545
  34. data/vendor/crates/spikard-core/src/di/mod.rs +0 -192
  35. data/vendor/crates/spikard-core/src/di/resolved.rs +0 -411
  36. data/vendor/crates/spikard-core/src/di/value.rs +0 -283
  37. data/vendor/crates/spikard-core/src/http.rs +0 -153
  38. data/vendor/crates/spikard-core/src/lib.rs +0 -28
  39. data/vendor/crates/spikard-core/src/lifecycle.rs +0 -422
  40. data/vendor/crates/spikard-core/src/parameters.rs +0 -719
  41. data/vendor/crates/spikard-core/src/problem.rs +0 -310
  42. data/vendor/crates/spikard-core/src/request_data.rs +0 -189
  43. data/vendor/crates/spikard-core/src/router.rs +0 -249
  44. data/vendor/crates/spikard-core/src/schema_registry.rs +0 -183
  45. data/vendor/crates/spikard-core/src/type_hints.rs +0 -304
  46. data/vendor/crates/spikard-core/src/validation.rs +0 -699
  47. data/vendor/crates/spikard-http/Cargo.toml +0 -58
  48. data/vendor/crates/spikard-http/src/auth.rs +0 -247
  49. data/vendor/crates/spikard-http/src/background.rs +0 -249
  50. data/vendor/crates/spikard-http/src/bindings/mod.rs +0 -3
  51. data/vendor/crates/spikard-http/src/bindings/response.rs +0 -1
  52. data/vendor/crates/spikard-http/src/body_metadata.rs +0 -8
  53. data/vendor/crates/spikard-http/src/cors.rs +0 -490
  54. data/vendor/crates/spikard-http/src/debug.rs +0 -63
  55. data/vendor/crates/spikard-http/src/di_handler.rs +0 -423
  56. data/vendor/crates/spikard-http/src/handler_response.rs +0 -190
  57. data/vendor/crates/spikard-http/src/handler_trait.rs +0 -228
  58. data/vendor/crates/spikard-http/src/handler_trait_tests.rs +0 -284
  59. data/vendor/crates/spikard-http/src/lib.rs +0 -529
  60. data/vendor/crates/spikard-http/src/lifecycle/adapter.rs +0 -149
  61. data/vendor/crates/spikard-http/src/lifecycle.rs +0 -428
  62. data/vendor/crates/spikard-http/src/middleware/mod.rs +0 -285
  63. data/vendor/crates/spikard-http/src/middleware/multipart.rs +0 -86
  64. data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +0 -147
  65. data/vendor/crates/spikard-http/src/middleware/validation.rs +0 -287
  66. data/vendor/crates/spikard-http/src/openapi/mod.rs +0 -309
  67. data/vendor/crates/spikard-http/src/openapi/parameter_extraction.rs +0 -190
  68. data/vendor/crates/spikard-http/src/openapi/schema_conversion.rs +0 -308
  69. data/vendor/crates/spikard-http/src/openapi/spec_generation.rs +0 -195
  70. data/vendor/crates/spikard-http/src/parameters.rs +0 -1
  71. data/vendor/crates/spikard-http/src/problem.rs +0 -1
  72. data/vendor/crates/spikard-http/src/query_parser.rs +0 -369
  73. data/vendor/crates/spikard-http/src/response.rs +0 -399
  74. data/vendor/crates/spikard-http/src/router.rs +0 -1
  75. data/vendor/crates/spikard-http/src/schema_registry.rs +0 -1
  76. data/vendor/crates/spikard-http/src/server/handler.rs +0 -80
  77. data/vendor/crates/spikard-http/src/server/lifecycle_execution.rs +0 -98
  78. data/vendor/crates/spikard-http/src/server/mod.rs +0 -805
  79. data/vendor/crates/spikard-http/src/server/request_extraction.rs +0 -119
  80. data/vendor/crates/spikard-http/src/sse.rs +0 -447
  81. data/vendor/crates/spikard-http/src/testing/form.rs +0 -14
  82. data/vendor/crates/spikard-http/src/testing/multipart.rs +0 -60
  83. data/vendor/crates/spikard-http/src/testing/test_client.rs +0 -285
  84. data/vendor/crates/spikard-http/src/testing.rs +0 -377
  85. data/vendor/crates/spikard-http/src/type_hints.rs +0 -1
  86. data/vendor/crates/spikard-http/src/validation.rs +0 -1
  87. data/vendor/crates/spikard-http/src/websocket.rs +0 -324
  88. data/vendor/crates/spikard-rb/Cargo.toml +0 -42
  89. data/vendor/crates/spikard-rb/build.rs +0 -8
  90. data/vendor/crates/spikard-rb/src/background.rs +0 -63
  91. data/vendor/crates/spikard-rb/src/config.rs +0 -294
  92. data/vendor/crates/spikard-rb/src/conversion.rs +0 -392
  93. data/vendor/crates/spikard-rb/src/di.rs +0 -409
  94. data/vendor/crates/spikard-rb/src/handler.rs +0 -534
  95. data/vendor/crates/spikard-rb/src/lib.rs +0 -2020
  96. data/vendor/crates/spikard-rb/src/lifecycle.rs +0 -267
  97. data/vendor/crates/spikard-rb/src/server.rs +0 -283
  98. data/vendor/crates/spikard-rb/src/sse.rs +0 -231
  99. data/vendor/crates/spikard-rb/src/test_client.rs +0 -404
  100. data/vendor/crates/spikard-rb/src/test_sse.rs +0 -143
  101. data/vendor/crates/spikard-rb/src/test_websocket.rs +0 -221
  102. data/vendor/crates/spikard-rb/src/websocket.rs +0 -233
  103. /data/vendor/bundle/ruby/{3.3.0 → 3.4.0}/gems/diff-lcs-1.6.2/mise.toml +0 -0
@@ -1,399 +0,0 @@
1
- //! HTTP Response types
2
- //!
3
- //! Response types for returning custom responses with status codes, headers, and content
4
-
5
- use serde_json::Value;
6
- use std::collections::HashMap;
7
-
8
- /// HTTP Response with custom status code, headers, and content
9
- #[derive(Debug, Clone)]
10
- pub struct Response {
11
- /// Response body content
12
- pub content: Option<Value>,
13
- /// HTTP status code (defaults to 200)
14
- pub status_code: u16,
15
- /// Response headers
16
- pub headers: HashMap<String, String>,
17
- }
18
-
19
- impl Response {
20
- /// Create a new Response with default status 200
21
- pub fn new(content: Option<Value>) -> Self {
22
- Self {
23
- content,
24
- status_code: 200,
25
- headers: HashMap::new(),
26
- }
27
- }
28
-
29
- /// Create a response with a specific status code
30
- pub fn with_status(content: Option<Value>, status_code: u16) -> Self {
31
- Self {
32
- content,
33
- status_code,
34
- headers: HashMap::new(),
35
- }
36
- }
37
-
38
- /// Set a header
39
- pub fn set_header(&mut self, key: String, value: String) {
40
- self.headers.insert(key, value);
41
- }
42
-
43
- /// Set a cookie in the response
44
- #[allow(clippy::too_many_arguments)]
45
- pub fn set_cookie(
46
- &mut self,
47
- key: String,
48
- value: String,
49
- max_age: Option<i64>,
50
- domain: Option<String>,
51
- path: Option<String>,
52
- secure: bool,
53
- http_only: bool,
54
- same_site: Option<String>,
55
- ) {
56
- let mut cookie_value = format!("{}={}", key, value);
57
-
58
- if let Some(age) = max_age {
59
- cookie_value.push_str(&format!("; Max-Age={}", age));
60
- }
61
- if let Some(d) = domain {
62
- cookie_value.push_str(&format!("; Domain={}", d));
63
- }
64
- if let Some(p) = path {
65
- cookie_value.push_str(&format!("; Path={}", p));
66
- }
67
- if secure {
68
- cookie_value.push_str("; Secure");
69
- }
70
- if http_only {
71
- cookie_value.push_str("; HttpOnly");
72
- }
73
- if let Some(ss) = same_site {
74
- cookie_value.push_str(&format!("; SameSite={}", ss));
75
- }
76
-
77
- self.headers.insert("set-cookie".to_string(), cookie_value);
78
- }
79
- }
80
-
81
- impl Default for Response {
82
- fn default() -> Self {
83
- Self::new(None)
84
- }
85
- }
86
-
87
- #[cfg(test)]
88
- mod tests {
89
- use super::*;
90
- use serde_json::json;
91
-
92
- #[test]
93
- fn response_new_creates_default_status() {
94
- let response = Response::new(None);
95
- assert_eq!(response.status_code, 200);
96
- assert!(response.headers.is_empty());
97
- assert!(response.content.is_none());
98
- }
99
-
100
- #[test]
101
- fn response_new_with_content() {
102
- let content = json!({"key": "value"});
103
- let response = Response::new(Some(content.clone()));
104
- assert_eq!(response.status_code, 200);
105
- assert_eq!(response.content, Some(content));
106
- }
107
-
108
- #[test]
109
- fn response_with_status() {
110
- let response = Response::with_status(None, 404);
111
- assert_eq!(response.status_code, 404);
112
- assert!(response.headers.is_empty());
113
- }
114
-
115
- #[test]
116
- fn response_with_status_and_content() {
117
- let content = json!({"error": "not found"});
118
- let response = Response::with_status(Some(content.clone()), 404);
119
- assert_eq!(response.status_code, 404);
120
- assert_eq!(response.content, Some(content));
121
- }
122
-
123
- #[test]
124
- fn response_set_header() {
125
- let mut response = Response::new(None);
126
- response.set_header("X-Custom".to_string(), "custom-value".to_string());
127
- assert_eq!(response.headers.get("X-Custom"), Some(&"custom-value".to_string()));
128
- }
129
-
130
- #[test]
131
- fn response_set_multiple_headers() {
132
- let mut response = Response::new(None);
133
- response.set_header("Content-Type".to_string(), "application/json".to_string());
134
- response.set_header("X-Custom".to_string(), "custom-value".to_string());
135
- assert_eq!(response.headers.len(), 2);
136
- assert_eq!(
137
- response.headers.get("Content-Type"),
138
- Some(&"application/json".to_string())
139
- );
140
- assert_eq!(response.headers.get("X-Custom"), Some(&"custom-value".to_string()));
141
- }
142
-
143
- #[test]
144
- fn response_set_header_overwrites() {
145
- let mut response = Response::new(None);
146
- response.set_header("X-Custom".to_string(), "value1".to_string());
147
- response.set_header("X-Custom".to_string(), "value2".to_string());
148
- assert_eq!(response.headers.get("X-Custom"), Some(&"value2".to_string()));
149
- }
150
-
151
- #[test]
152
- fn response_set_cookie_minimal() {
153
- let mut response = Response::new(None);
154
- response.set_cookie(
155
- "session_id".to_string(),
156
- "abc123".to_string(),
157
- None,
158
- None,
159
- None,
160
- false,
161
- false,
162
- None,
163
- );
164
- let cookie = response.headers.get("set-cookie").unwrap();
165
- assert_eq!(cookie, "session_id=abc123");
166
- }
167
-
168
- #[test]
169
- fn response_set_cookie_with_max_age() {
170
- let mut response = Response::new(None);
171
- response.set_cookie(
172
- "session".to_string(),
173
- "token".to_string(),
174
- Some(3600),
175
- None,
176
- None,
177
- false,
178
- false,
179
- None,
180
- );
181
- let cookie = response.headers.get("set-cookie").unwrap();
182
- assert!(cookie.contains("session=token"));
183
- assert!(cookie.contains("Max-Age=3600"));
184
- }
185
-
186
- #[test]
187
- fn response_set_cookie_with_domain() {
188
- let mut response = Response::new(None);
189
- response.set_cookie(
190
- "session".to_string(),
191
- "token".to_string(),
192
- None,
193
- Some("example.com".to_string()),
194
- None,
195
- false,
196
- false,
197
- None,
198
- );
199
- let cookie = response.headers.get("set-cookie").unwrap();
200
- assert!(cookie.contains("Domain=example.com"));
201
- }
202
-
203
- #[test]
204
- fn response_set_cookie_with_path() {
205
- let mut response = Response::new(None);
206
- response.set_cookie(
207
- "session".to_string(),
208
- "token".to_string(),
209
- None,
210
- None,
211
- Some("/app".to_string()),
212
- false,
213
- false,
214
- None,
215
- );
216
- let cookie = response.headers.get("set-cookie").unwrap();
217
- assert!(cookie.contains("Path=/app"));
218
- }
219
-
220
- #[test]
221
- fn response_set_cookie_secure() {
222
- let mut response = Response::new(None);
223
- response.set_cookie(
224
- "session".to_string(),
225
- "token".to_string(),
226
- None,
227
- None,
228
- None,
229
- true,
230
- false,
231
- None,
232
- );
233
- let cookie = response.headers.get("set-cookie").unwrap();
234
- assert!(cookie.contains("Secure"));
235
- }
236
-
237
- #[test]
238
- fn response_set_cookie_http_only() {
239
- let mut response = Response::new(None);
240
- response.set_cookie(
241
- "session".to_string(),
242
- "token".to_string(),
243
- None,
244
- None,
245
- None,
246
- false,
247
- true,
248
- None,
249
- );
250
- let cookie = response.headers.get("set-cookie").unwrap();
251
- assert!(cookie.contains("HttpOnly"));
252
- }
253
-
254
- #[test]
255
- fn response_set_cookie_same_site() {
256
- let mut response = Response::new(None);
257
- response.set_cookie(
258
- "session".to_string(),
259
- "token".to_string(),
260
- None,
261
- None,
262
- None,
263
- false,
264
- false,
265
- Some("Strict".to_string()),
266
- );
267
- let cookie = response.headers.get("set-cookie").unwrap();
268
- assert!(cookie.contains("SameSite=Strict"));
269
- }
270
-
271
- #[test]
272
- fn response_set_cookie_all_attributes() {
273
- let mut response = Response::new(None);
274
- response.set_cookie(
275
- "session".to_string(),
276
- "token123".to_string(),
277
- Some(3600),
278
- Some("example.com".to_string()),
279
- Some("/app".to_string()),
280
- true,
281
- true,
282
- Some("Lax".to_string()),
283
- );
284
- let cookie = response.headers.get("set-cookie").unwrap();
285
- assert!(cookie.contains("session=token123"));
286
- assert!(cookie.contains("Max-Age=3600"));
287
- assert!(cookie.contains("Domain=example.com"));
288
- assert!(cookie.contains("Path=/app"));
289
- assert!(cookie.contains("Secure"));
290
- assert!(cookie.contains("HttpOnly"));
291
- assert!(cookie.contains("SameSite=Lax"));
292
- }
293
-
294
- #[test]
295
- fn response_set_cookie_overwrites_previous() {
296
- let mut response = Response::new(None);
297
- response.set_cookie(
298
- "session".to_string(),
299
- "old_token".to_string(),
300
- None,
301
- None,
302
- None,
303
- false,
304
- false,
305
- None,
306
- );
307
- response.set_cookie(
308
- "session".to_string(),
309
- "new_token".to_string(),
310
- None,
311
- None,
312
- None,
313
- false,
314
- false,
315
- None,
316
- );
317
- let cookie = response.headers.get("set-cookie").unwrap();
318
- assert!(cookie.contains("new_token"));
319
- assert!(!cookie.contains("old_token"));
320
- }
321
-
322
- #[test]
323
- fn response_default() {
324
- let response = Response::default();
325
- assert_eq!(response.status_code, 200);
326
- assert!(response.headers.is_empty());
327
- assert!(response.content.is_none());
328
- }
329
-
330
- #[test]
331
- fn response_cookie_with_special_chars_in_value() {
332
- let mut response = Response::new(None);
333
- response.set_cookie(
334
- "name".to_string(),
335
- "value%3D123".to_string(),
336
- None,
337
- None,
338
- None,
339
- false,
340
- false,
341
- None,
342
- );
343
- let cookie = response.headers.get("set-cookie").unwrap();
344
- assert_eq!(cookie, "name=value%3D123");
345
- }
346
-
347
- #[test]
348
- fn response_same_site_variants() {
349
- for same_site in &["Strict", "Lax", "None"] {
350
- let mut response = Response::new(None);
351
- response.set_cookie(
352
- "test".to_string(),
353
- "value".to_string(),
354
- None,
355
- None,
356
- None,
357
- false,
358
- false,
359
- Some(same_site.to_string()),
360
- );
361
- let cookie = response.headers.get("set-cookie").unwrap();
362
- assert!(cookie.contains(&format!("SameSite={}", same_site)));
363
- }
364
- }
365
-
366
- #[test]
367
- fn response_zero_max_age() {
368
- let mut response = Response::new(None);
369
- response.set_cookie(
370
- "session".to_string(),
371
- "token".to_string(),
372
- Some(0),
373
- None,
374
- None,
375
- false,
376
- false,
377
- None,
378
- );
379
- let cookie = response.headers.get("set-cookie").unwrap();
380
- assert!(cookie.contains("Max-Age=0"));
381
- }
382
-
383
- #[test]
384
- fn response_negative_max_age() {
385
- let mut response = Response::new(None);
386
- response.set_cookie(
387
- "session".to_string(),
388
- "token".to_string(),
389
- Some(-1),
390
- None,
391
- None,
392
- false,
393
- false,
394
- None,
395
- );
396
- let cookie = response.headers.get("set-cookie").unwrap();
397
- assert!(cookie.contains("Max-Age=-1"));
398
- }
399
- }
@@ -1 +0,0 @@
1
- pub use spikard_core::router::*;
@@ -1 +0,0 @@
1
- pub use spikard_core::schema_registry::*;
@@ -1,80 +0,0 @@
1
- //! ValidatingHandler wrapper that executes request/parameter validation before handler
2
-
3
- use crate::ProblemDetails;
4
- use crate::handler_trait::{Handler, HandlerResult, RequestData};
5
- use crate::parameters::ParameterValidator;
6
- use crate::validation::SchemaValidator;
7
- use axum::body::Body;
8
- use serde_json::Value;
9
- use std::collections::HashMap;
10
- use std::future::Future;
11
- use std::pin::Pin;
12
- use std::sync::Arc;
13
-
14
- /// Wrapper that runs request/parameter validation before calling the user handler.
15
- pub struct ValidatingHandler {
16
- inner: Arc<dyn Handler>,
17
- request_validator: Option<Arc<SchemaValidator>>,
18
- parameter_validator: Option<ParameterValidator>,
19
- }
20
-
21
- impl ValidatingHandler {
22
- /// Create a new validating handler wrapping the inner handler with schema validators
23
- pub fn new(inner: Arc<dyn Handler>, route: &crate::Route) -> Self {
24
- Self {
25
- inner,
26
- request_validator: route.request_validator.clone(),
27
- parameter_validator: route.parameter_validator.clone(),
28
- }
29
- }
30
- }
31
-
32
- impl Handler for ValidatingHandler {
33
- fn call(
34
- &self,
35
- req: axum::http::Request<Body>,
36
- mut request_data: RequestData,
37
- ) -> Pin<Box<dyn Future<Output = HandlerResult> + Send + '_>> {
38
- let inner = self.inner.clone();
39
- let request_validator = self.request_validator.clone();
40
- let parameter_validator = self.parameter_validator.clone();
41
-
42
- Box::pin(async move {
43
- if let Some(validator) = request_validator {
44
- if request_data.body.is_null() && request_data.raw_body.is_some() {
45
- let raw_bytes = request_data.raw_body.as_ref().unwrap();
46
- request_data.body = serde_json::from_slice::<Value>(raw_bytes)
47
- .map_err(|e| (axum::http::StatusCode::BAD_REQUEST, format!("Invalid JSON: {}", e)))?;
48
- }
49
-
50
- if let Err(errors) = validator.validate(&request_data.body) {
51
- let problem = ProblemDetails::from_validation_error(&errors);
52
- let body = problem.to_json().unwrap_or_else(|_| "{}".to_string());
53
- return Err((problem.status_code(), body));
54
- }
55
- }
56
-
57
- if let Some(validator) = parameter_validator {
58
- let raw_query_strings: HashMap<String, String> = request_data
59
- .raw_query_params
60
- .iter()
61
- .filter_map(|(k, v)| v.first().map(|value| (k.clone(), value.clone())))
62
- .collect();
63
-
64
- if let Err(errors) = validator.validate_and_extract(
65
- &request_data.query_params,
66
- &raw_query_strings,
67
- &request_data.path_params,
68
- &request_data.headers,
69
- &request_data.cookies,
70
- ) {
71
- let problem = ProblemDetails::from_validation_error(&errors);
72
- let body = problem.to_json().unwrap_or_else(|_| "{}".to_string());
73
- return Err((problem.status_code(), body));
74
- }
75
- }
76
-
77
- inner.call(req, request_data).await
78
- })
79
- }
80
- }
@@ -1,98 +0,0 @@
1
- //! Lifecycle hooks execution logic
2
-
3
- use crate::handler_trait::Handler;
4
- use axum::body::Body;
5
- use axum::http::StatusCode;
6
- use std::sync::Arc;
7
-
8
- /// Execute a handler with lifecycle hooks
9
- ///
10
- /// This wraps the handler execution with lifecycle hooks at appropriate points:
11
- /// 1. preValidation hooks (before handler, which does validation)
12
- /// 2. preHandler hooks (after validation, before handler)
13
- /// 3. Handler execution
14
- /// 4. onResponse hooks (after successful handler execution)
15
- /// 5. onError hooks (if handler or any hook fails)
16
- pub async fn execute_with_lifecycle_hooks(
17
- req: axum::http::Request<Body>,
18
- request_data: crate::handler_trait::RequestData,
19
- handler: Arc<dyn Handler>,
20
- hooks: Option<Arc<crate::LifecycleHooks>>,
21
- ) -> Result<axum::http::Response<Body>, (axum::http::StatusCode, String)> {
22
- use crate::lifecycle::HookResult;
23
-
24
- let Some(hooks) = hooks else {
25
- return handler.call(req, request_data).await;
26
- };
27
-
28
- if hooks.is_empty() {
29
- return handler.call(req, request_data).await;
30
- }
31
-
32
- let req = match hooks.execute_pre_validation(req).await {
33
- Ok(HookResult::Continue(r)) => r,
34
- Ok(HookResult::ShortCircuit(response)) => return Ok(response),
35
- Err(e) => {
36
- let error_response = axum::http::Response::builder()
37
- .status(StatusCode::INTERNAL_SERVER_ERROR)
38
- .body(Body::from(format!(
39
- "{{\"error\":\"preValidation hook failed: {}\"}}",
40
- e
41
- )))
42
- .unwrap();
43
-
44
- return match hooks.execute_on_error(error_response).await {
45
- Ok(resp) => Ok(resp),
46
- Err(_) => Ok(axum::http::Response::builder()
47
- .status(StatusCode::INTERNAL_SERVER_ERROR)
48
- .body(Body::from("{\"error\":\"Hook execution failed\"}"))
49
- .unwrap()),
50
- };
51
- }
52
- };
53
-
54
- let req = match hooks.execute_pre_handler(req).await {
55
- Ok(HookResult::Continue(r)) => r,
56
- Ok(HookResult::ShortCircuit(response)) => return Ok(response),
57
- Err(e) => {
58
- let error_response = axum::http::Response::builder()
59
- .status(StatusCode::INTERNAL_SERVER_ERROR)
60
- .body(Body::from(format!("{{\"error\":\"preHandler hook failed: {}\"}}", e)))
61
- .unwrap();
62
-
63
- return match hooks.execute_on_error(error_response).await {
64
- Ok(resp) => Ok(resp),
65
- Err(_) => Ok(axum::http::Response::builder()
66
- .status(StatusCode::INTERNAL_SERVER_ERROR)
67
- .body(Body::from("{\"error\":\"Hook execution failed\"}"))
68
- .unwrap()),
69
- };
70
- }
71
- };
72
-
73
- let response = match handler.call(req, request_data).await {
74
- Ok(resp) => resp,
75
- Err((status, message)) => {
76
- let error_response = axum::http::Response::builder()
77
- .status(status)
78
- .body(Body::from(message))
79
- .unwrap();
80
-
81
- return match hooks.execute_on_error(error_response).await {
82
- Ok(resp) => Ok(resp),
83
- Err(e) => Ok(axum::http::Response::builder()
84
- .status(StatusCode::INTERNAL_SERVER_ERROR)
85
- .body(Body::from(format!("{{\"error\":\"onError hook failed: {}\"}}", e)))
86
- .unwrap()),
87
- };
88
- }
89
- };
90
-
91
- match hooks.execute_on_response(response).await {
92
- Ok(resp) => Ok(resp),
93
- Err(e) => Ok(axum::http::Response::builder()
94
- .status(StatusCode::INTERNAL_SERVER_ERROR)
95
- .body(Body::from(format!("{{\"error\":\"onResponse hook failed: {}\"}}", e)))
96
- .unwrap()),
97
- }
98
- }