spikard 0.2.5 → 0.3.0

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -1
  3. data/ext/spikard_rb/Cargo.toml +3 -3
  4. data/lib/spikard/app.rb +61 -49
  5. data/lib/spikard/converters.rb +3 -75
  6. data/lib/spikard/handler_wrapper.rb +6 -9
  7. data/lib/spikard/provide.rb +14 -28
  8. data/lib/spikard/response.rb +75 -11
  9. data/lib/spikard/streaming_response.rb +24 -1
  10. data/lib/spikard/testing.rb +1 -1
  11. data/lib/spikard/version.rb +1 -1
  12. data/sig/spikard.rbs +14 -3
  13. data/vendor/bundle/ruby/3.3.0/gems/rake-compiler-dock-1.10.0/build/buildkitd.toml +2 -0
  14. metadata +3 -80
  15. data/vendor/crates/spikard-core/Cargo.toml +0 -40
  16. data/vendor/crates/spikard-core/src/bindings/mod.rs +0 -3
  17. data/vendor/crates/spikard-core/src/bindings/response.rs +0 -133
  18. data/vendor/crates/spikard-core/src/debug.rs +0 -63
  19. data/vendor/crates/spikard-core/src/di/container.rs +0 -726
  20. data/vendor/crates/spikard-core/src/di/dependency.rs +0 -273
  21. data/vendor/crates/spikard-core/src/di/error.rs +0 -118
  22. data/vendor/crates/spikard-core/src/di/factory.rs +0 -538
  23. data/vendor/crates/spikard-core/src/di/graph.rs +0 -545
  24. data/vendor/crates/spikard-core/src/di/mod.rs +0 -192
  25. data/vendor/crates/spikard-core/src/di/resolved.rs +0 -411
  26. data/vendor/crates/spikard-core/src/di/value.rs +0 -283
  27. data/vendor/crates/spikard-core/src/http.rs +0 -153
  28. data/vendor/crates/spikard-core/src/lib.rs +0 -28
  29. data/vendor/crates/spikard-core/src/lifecycle.rs +0 -422
  30. data/vendor/crates/spikard-core/src/parameters.rs +0 -719
  31. data/vendor/crates/spikard-core/src/problem.rs +0 -310
  32. data/vendor/crates/spikard-core/src/request_data.rs +0 -189
  33. data/vendor/crates/spikard-core/src/router.rs +0 -249
  34. data/vendor/crates/spikard-core/src/schema_registry.rs +0 -183
  35. data/vendor/crates/spikard-core/src/type_hints.rs +0 -304
  36. data/vendor/crates/spikard-core/src/validation.rs +0 -699
  37. data/vendor/crates/spikard-http/Cargo.toml +0 -58
  38. data/vendor/crates/spikard-http/src/auth.rs +0 -247
  39. data/vendor/crates/spikard-http/src/background.rs +0 -249
  40. data/vendor/crates/spikard-http/src/bindings/mod.rs +0 -3
  41. data/vendor/crates/spikard-http/src/bindings/response.rs +0 -1
  42. data/vendor/crates/spikard-http/src/body_metadata.rs +0 -8
  43. data/vendor/crates/spikard-http/src/cors.rs +0 -490
  44. data/vendor/crates/spikard-http/src/debug.rs +0 -63
  45. data/vendor/crates/spikard-http/src/di_handler.rs +0 -423
  46. data/vendor/crates/spikard-http/src/handler_response.rs +0 -190
  47. data/vendor/crates/spikard-http/src/handler_trait.rs +0 -228
  48. data/vendor/crates/spikard-http/src/handler_trait_tests.rs +0 -284
  49. data/vendor/crates/spikard-http/src/lib.rs +0 -529
  50. data/vendor/crates/spikard-http/src/lifecycle/adapter.rs +0 -149
  51. data/vendor/crates/spikard-http/src/lifecycle.rs +0 -428
  52. data/vendor/crates/spikard-http/src/middleware/mod.rs +0 -285
  53. data/vendor/crates/spikard-http/src/middleware/multipart.rs +0 -86
  54. data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +0 -147
  55. data/vendor/crates/spikard-http/src/middleware/validation.rs +0 -287
  56. data/vendor/crates/spikard-http/src/openapi/mod.rs +0 -309
  57. data/vendor/crates/spikard-http/src/openapi/parameter_extraction.rs +0 -190
  58. data/vendor/crates/spikard-http/src/openapi/schema_conversion.rs +0 -308
  59. data/vendor/crates/spikard-http/src/openapi/spec_generation.rs +0 -195
  60. data/vendor/crates/spikard-http/src/parameters.rs +0 -1
  61. data/vendor/crates/spikard-http/src/problem.rs +0 -1
  62. data/vendor/crates/spikard-http/src/query_parser.rs +0 -369
  63. data/vendor/crates/spikard-http/src/response.rs +0 -399
  64. data/vendor/crates/spikard-http/src/router.rs +0 -1
  65. data/vendor/crates/spikard-http/src/schema_registry.rs +0 -1
  66. data/vendor/crates/spikard-http/src/server/handler.rs +0 -80
  67. data/vendor/crates/spikard-http/src/server/lifecycle_execution.rs +0 -98
  68. data/vendor/crates/spikard-http/src/server/mod.rs +0 -805
  69. data/vendor/crates/spikard-http/src/server/request_extraction.rs +0 -119
  70. data/vendor/crates/spikard-http/src/sse.rs +0 -447
  71. data/vendor/crates/spikard-http/src/testing/form.rs +0 -14
  72. data/vendor/crates/spikard-http/src/testing/multipart.rs +0 -60
  73. data/vendor/crates/spikard-http/src/testing/test_client.rs +0 -285
  74. data/vendor/crates/spikard-http/src/testing.rs +0 -377
  75. data/vendor/crates/spikard-http/src/type_hints.rs +0 -1
  76. data/vendor/crates/spikard-http/src/validation.rs +0 -1
  77. data/vendor/crates/spikard-http/src/websocket.rs +0 -324
  78. data/vendor/crates/spikard-rb/Cargo.toml +0 -42
  79. data/vendor/crates/spikard-rb/build.rs +0 -8
  80. data/vendor/crates/spikard-rb/src/background.rs +0 -63
  81. data/vendor/crates/spikard-rb/src/config.rs +0 -294
  82. data/vendor/crates/spikard-rb/src/conversion.rs +0 -392
  83. data/vendor/crates/spikard-rb/src/di.rs +0 -409
  84. data/vendor/crates/spikard-rb/src/handler.rs +0 -534
  85. data/vendor/crates/spikard-rb/src/lib.rs +0 -2020
  86. data/vendor/crates/spikard-rb/src/lifecycle.rs +0 -267
  87. data/vendor/crates/spikard-rb/src/server.rs +0 -283
  88. data/vendor/crates/spikard-rb/src/sse.rs +0 -231
  89. data/vendor/crates/spikard-rb/src/test_client.rs +0 -404
  90. data/vendor/crates/spikard-rb/src/test_sse.rs +0 -143
  91. data/vendor/crates/spikard-rb/src/test_websocket.rs +0 -221
  92. data/vendor/crates/spikard-rb/src/websocket.rs +0 -233
@@ -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
- }