spikard 0.3.6 → 0.5.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.
- checksums.yaml +4 -4
- data/README.md +21 -6
- data/ext/spikard_rb/Cargo.toml +2 -2
- data/lib/spikard/app.rb +33 -14
- data/lib/spikard/testing.rb +47 -12
- data/lib/spikard/version.rb +1 -1
- data/vendor/crates/spikard-bindings-shared/Cargo.toml +63 -0
- data/vendor/crates/spikard-bindings-shared/examples/config_extraction.rs +132 -0
- data/vendor/crates/spikard-bindings-shared/src/config_extractor.rs +752 -0
- data/vendor/crates/spikard-bindings-shared/src/conversion_traits.rs +194 -0
- data/vendor/crates/spikard-bindings-shared/src/di_traits.rs +246 -0
- data/vendor/crates/spikard-bindings-shared/src/error_response.rs +401 -0
- data/vendor/crates/spikard-bindings-shared/src/handler_base.rs +238 -0
- data/vendor/crates/spikard-bindings-shared/src/lib.rs +24 -0
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_base.rs +292 -0
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_executor.rs +616 -0
- data/vendor/crates/spikard-bindings-shared/src/response_builder.rs +305 -0
- data/vendor/crates/spikard-bindings-shared/src/test_client_base.rs +248 -0
- data/vendor/crates/spikard-bindings-shared/src/validation_helpers.rs +351 -0
- data/vendor/crates/spikard-bindings-shared/tests/comprehensive_coverage.rs +454 -0
- data/vendor/crates/spikard-bindings-shared/tests/error_response_edge_cases.rs +383 -0
- data/vendor/crates/spikard-bindings-shared/tests/handler_base_integration.rs +280 -0
- data/vendor/crates/spikard-core/Cargo.toml +4 -4
- data/vendor/crates/spikard-core/src/debug.rs +64 -0
- data/vendor/crates/spikard-core/src/di/container.rs +3 -27
- data/vendor/crates/spikard-core/src/di/factory.rs +1 -5
- data/vendor/crates/spikard-core/src/di/graph.rs +8 -47
- data/vendor/crates/spikard-core/src/di/mod.rs +1 -1
- data/vendor/crates/spikard-core/src/di/resolved.rs +1 -7
- data/vendor/crates/spikard-core/src/di/value.rs +2 -4
- data/vendor/crates/spikard-core/src/errors.rs +30 -0
- data/vendor/crates/spikard-core/src/http.rs +262 -0
- data/vendor/crates/spikard-core/src/lib.rs +1 -1
- data/vendor/crates/spikard-core/src/lifecycle.rs +764 -0
- data/vendor/crates/spikard-core/src/metadata.rs +389 -0
- data/vendor/crates/spikard-core/src/parameters.rs +1962 -159
- data/vendor/crates/spikard-core/src/problem.rs +34 -0
- data/vendor/crates/spikard-core/src/request_data.rs +966 -1
- data/vendor/crates/spikard-core/src/router.rs +263 -2
- data/vendor/crates/spikard-core/src/validation/error_mapper.rs +688 -0
- data/vendor/crates/spikard-core/src/{validation.rs → validation/mod.rs} +26 -268
- data/vendor/crates/spikard-http/Cargo.toml +12 -16
- data/vendor/crates/spikard-http/examples/sse-notifications.rs +148 -0
- data/vendor/crates/spikard-http/examples/websocket-chat.rs +92 -0
- data/vendor/crates/spikard-http/src/auth.rs +65 -16
- data/vendor/crates/spikard-http/src/background.rs +1614 -3
- data/vendor/crates/spikard-http/src/cors.rs +515 -0
- data/vendor/crates/spikard-http/src/debug.rs +65 -0
- data/vendor/crates/spikard-http/src/di_handler.rs +1322 -77
- data/vendor/crates/spikard-http/src/handler_response.rs +711 -0
- data/vendor/crates/spikard-http/src/handler_trait.rs +607 -5
- data/vendor/crates/spikard-http/src/handler_trait_tests.rs +6 -0
- data/vendor/crates/spikard-http/src/lib.rs +33 -28
- data/vendor/crates/spikard-http/src/lifecycle/adapter.rs +81 -0
- data/vendor/crates/spikard-http/src/lifecycle.rs +765 -0
- data/vendor/crates/spikard-http/src/middleware/mod.rs +372 -117
- data/vendor/crates/spikard-http/src/middleware/multipart.rs +836 -10
- data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +409 -43
- data/vendor/crates/spikard-http/src/middleware/validation.rs +513 -65
- data/vendor/crates/spikard-http/src/openapi/parameter_extraction.rs +345 -0
- data/vendor/crates/spikard-http/src/openapi/schema_conversion.rs +1055 -0
- data/vendor/crates/spikard-http/src/openapi/spec_generation.rs +473 -3
- data/vendor/crates/spikard-http/src/query_parser.rs +455 -31
- data/vendor/crates/spikard-http/src/response.rs +321 -0
- data/vendor/crates/spikard-http/src/server/handler.rs +1572 -9
- data/vendor/crates/spikard-http/src/server/lifecycle_execution.rs +136 -0
- data/vendor/crates/spikard-http/src/server/mod.rs +875 -178
- data/vendor/crates/spikard-http/src/server/request_extraction.rs +674 -23
- data/vendor/crates/spikard-http/src/server/routing_factory.rs +599 -0
- data/vendor/crates/spikard-http/src/sse.rs +983 -21
- data/vendor/crates/spikard-http/src/testing/form.rs +38 -0
- data/vendor/crates/spikard-http/src/testing/test_client.rs +0 -2
- data/vendor/crates/spikard-http/src/testing.rs +7 -7
- data/vendor/crates/spikard-http/src/websocket.rs +1055 -4
- data/vendor/crates/spikard-http/tests/background_behavior.rs +832 -0
- data/vendor/crates/spikard-http/tests/common/handlers.rs +309 -0
- data/vendor/crates/spikard-http/tests/common/mod.rs +26 -0
- data/vendor/crates/spikard-http/tests/di_integration.rs +192 -0
- data/vendor/crates/spikard-http/tests/doc_snippets.rs +5 -0
- data/vendor/crates/spikard-http/tests/lifecycle_execution.rs +1093 -0
- data/vendor/crates/spikard-http/tests/multipart_behavior.rs +656 -0
- data/vendor/crates/spikard-http/tests/server_config_builder.rs +314 -0
- data/vendor/crates/spikard-http/tests/sse_behavior.rs +620 -0
- data/vendor/crates/spikard-http/tests/websocket_behavior.rs +663 -0
- data/vendor/crates/spikard-rb/Cargo.toml +10 -4
- data/vendor/crates/spikard-rb/build.rs +196 -5
- data/vendor/crates/spikard-rb/src/config/mod.rs +5 -0
- data/vendor/crates/spikard-rb/src/{config.rs → config/server_config.rs} +100 -109
- data/vendor/crates/spikard-rb/src/conversion.rs +121 -20
- data/vendor/crates/spikard-rb/src/di/builder.rs +100 -0
- data/vendor/crates/spikard-rb/src/{di.rs → di/mod.rs} +12 -46
- data/vendor/crates/spikard-rb/src/handler.rs +100 -107
- data/vendor/crates/spikard-rb/src/integration/mod.rs +3 -0
- data/vendor/crates/spikard-rb/src/lib.rs +467 -1428
- data/vendor/crates/spikard-rb/src/lifecycle.rs +1 -0
- data/vendor/crates/spikard-rb/src/metadata/mod.rs +5 -0
- data/vendor/crates/spikard-rb/src/metadata/route_extraction.rs +447 -0
- data/vendor/crates/spikard-rb/src/runtime/mod.rs +5 -0
- data/vendor/crates/spikard-rb/src/runtime/server_runner.rs +324 -0
- data/vendor/crates/spikard-rb/src/server.rs +47 -22
- data/vendor/crates/spikard-rb/src/{test_client.rs → testing/client.rs} +187 -40
- data/vendor/crates/spikard-rb/src/testing/mod.rs +7 -0
- data/vendor/crates/spikard-rb/src/testing/websocket.rs +635 -0
- data/vendor/crates/spikard-rb/src/websocket.rs +178 -37
- metadata +46 -13
- data/vendor/crates/spikard-http/src/parameters.rs +0 -1
- data/vendor/crates/spikard-http/src/problem.rs +0 -1
- data/vendor/crates/spikard-http/src/router.rs +0 -1
- data/vendor/crates/spikard-http/src/schema_registry.rs +0 -1
- data/vendor/crates/spikard-http/src/type_hints.rs +0 -1
- data/vendor/crates/spikard-http/src/validation.rs +0 -1
- data/vendor/crates/spikard-rb/src/test_websocket.rs +0 -221
- /data/vendor/crates/spikard-rb/src/{test_sse.rs → testing/sse.rs} +0 -0
|
@@ -100,6 +100,7 @@ mod tests {
|
|
|
100
100
|
let request_data = RequestData {
|
|
101
101
|
path_params: Arc::new(path_params),
|
|
102
102
|
query_params: json!({"page": 1}),
|
|
103
|
+
validated_params: None,
|
|
103
104
|
raw_query_params: Arc::new(HashMap::new()),
|
|
104
105
|
body: json!({"test": "data"}),
|
|
105
106
|
raw_body: None,
|
|
@@ -131,6 +132,7 @@ mod tests {
|
|
|
131
132
|
let request_data = RequestData {
|
|
132
133
|
path_params: Arc::new(HashMap::new()),
|
|
133
134
|
query_params: Value::Null,
|
|
135
|
+
validated_params: None,
|
|
134
136
|
raw_query_params: Arc::new(HashMap::new()),
|
|
135
137
|
body: Value::Null,
|
|
136
138
|
raw_body: None,
|
|
@@ -169,6 +171,7 @@ mod tests {
|
|
|
169
171
|
let request_data = RequestData {
|
|
170
172
|
path_params: Arc::new(HashMap::new()),
|
|
171
173
|
query_params: json!({"api_key": "secret123"}),
|
|
174
|
+
validated_params: None,
|
|
172
175
|
raw_query_params: Arc::new(raw_query_params.clone()),
|
|
173
176
|
body: Value::Null,
|
|
174
177
|
raw_body: None,
|
|
@@ -192,6 +195,7 @@ mod tests {
|
|
|
192
195
|
let request_data_no_param = RequestData {
|
|
193
196
|
path_params: Arc::new(HashMap::new()),
|
|
194
197
|
query_params: Value::Null,
|
|
198
|
+
validated_params: None,
|
|
195
199
|
raw_query_params: Arc::new(HashMap::new()),
|
|
196
200
|
body: Value::Null,
|
|
197
201
|
raw_body: None,
|
|
@@ -229,6 +233,7 @@ mod tests {
|
|
|
229
233
|
let request_data = RequestData {
|
|
230
234
|
path_params: Arc::new(path_params),
|
|
231
235
|
query_params: json!({"filter": "active"}),
|
|
236
|
+
validated_params: None,
|
|
232
237
|
raw_query_params: Arc::new(raw_query_params),
|
|
233
238
|
body: json!({"name": "test"}),
|
|
234
239
|
raw_body: None,
|
|
@@ -254,6 +259,7 @@ mod tests {
|
|
|
254
259
|
let request_data = RequestData {
|
|
255
260
|
path_params: Arc::new(HashMap::new()),
|
|
256
261
|
query_params: Value::Null,
|
|
262
|
+
validated_params: None,
|
|
257
263
|
raw_query_params: Arc::new(HashMap::new()),
|
|
258
264
|
body: Value::Null,
|
|
259
265
|
raw_body: None,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
#![allow(clippy::pedantic, clippy::nursery)]
|
|
2
|
+
#![cfg_attr(test, allow(clippy::all))]
|
|
1
3
|
//! Spikard HTTP Server
|
|
2
4
|
//!
|
|
3
5
|
//! Pure Rust HTTP server with language-agnostic handler trait.
|
|
@@ -13,20 +15,15 @@ pub mod debug;
|
|
|
13
15
|
pub mod di_handler;
|
|
14
16
|
pub mod handler_response;
|
|
15
17
|
pub mod handler_trait;
|
|
18
|
+
pub mod jsonrpc;
|
|
16
19
|
pub mod lifecycle;
|
|
17
20
|
pub mod middleware;
|
|
18
21
|
pub mod openapi;
|
|
19
|
-
pub mod parameters;
|
|
20
|
-
pub mod problem;
|
|
21
22
|
pub mod query_parser;
|
|
22
23
|
pub mod response;
|
|
23
|
-
pub mod router;
|
|
24
|
-
pub mod schema_registry;
|
|
25
24
|
pub mod server;
|
|
26
25
|
pub mod sse;
|
|
27
26
|
pub mod testing;
|
|
28
|
-
pub mod type_hints;
|
|
29
|
-
pub mod validation;
|
|
30
27
|
pub mod websocket;
|
|
31
28
|
|
|
32
29
|
use serde::{Deserialize, Serialize};
|
|
@@ -44,20 +41,22 @@ pub use body_metadata::ResponseBodySize;
|
|
|
44
41
|
pub use di_handler::DependencyInjectingHandler;
|
|
45
42
|
pub use handler_response::HandlerResponse;
|
|
46
43
|
pub use handler_trait::{Handler, HandlerResult, RequestData, ValidatedParams};
|
|
44
|
+
pub use jsonrpc::JsonRpcConfig;
|
|
47
45
|
pub use lifecycle::{HookResult, LifecycleHook, LifecycleHooks, LifecycleHooksBuilder, request_hook, response_hook};
|
|
48
46
|
pub use openapi::{ContactInfo, LicenseInfo, OpenApiConfig, SecuritySchemeInfo, ServerInfo};
|
|
49
|
-
pub use parameters::ParameterValidator;
|
|
50
|
-
pub use problem::{CONTENT_TYPE_PROBLEM_JSON, ProblemDetails};
|
|
51
47
|
pub use response::Response;
|
|
52
|
-
pub use router::{Route, RouteHandler, Router};
|
|
53
|
-
pub use schema_registry::SchemaRegistry;
|
|
54
48
|
pub use server::Server;
|
|
55
|
-
pub use spikard_core::{
|
|
49
|
+
pub use spikard_core::{
|
|
50
|
+
CompressionConfig, CorsConfig, Method, ParameterValidator, ProblemDetails, RateLimitConfig, Route, RouteHandler,
|
|
51
|
+
RouteMetadata, Router, SchemaRegistry, SchemaValidator,
|
|
52
|
+
};
|
|
56
53
|
pub use sse::{SseEvent, SseEventProducer, SseState, sse_handler};
|
|
57
54
|
pub use testing::{ResponseSnapshot, SnapshotError, snapshot_response};
|
|
58
|
-
pub use validation::SchemaValidator;
|
|
59
55
|
pub use websocket::{WebSocketHandler, WebSocketState, websocket_handler};
|
|
60
56
|
|
|
57
|
+
/// Reexport from spikard_core for convenience
|
|
58
|
+
pub use spikard_core::problem::CONTENT_TYPE_PROBLEM_JSON;
|
|
59
|
+
|
|
61
60
|
/// JWT authentication configuration
|
|
62
61
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
63
62
|
pub struct JwtConfig {
|
|
@@ -139,10 +138,14 @@ pub struct ServerConfig {
|
|
|
139
138
|
pub shutdown_timeout: u64,
|
|
140
139
|
/// OpenAPI documentation configuration
|
|
141
140
|
pub openapi: Option<crate::openapi::OpenApiConfig>,
|
|
141
|
+
/// JSON-RPC configuration
|
|
142
|
+
pub jsonrpc: Option<crate::jsonrpc::JsonRpcConfig>,
|
|
142
143
|
/// Lifecycle hooks for request/response processing
|
|
143
144
|
pub lifecycle_hooks: Option<std::sync::Arc<LifecycleHooks>>,
|
|
144
145
|
/// Background task executor configuration
|
|
145
146
|
pub background_tasks: BackgroundTaskConfig,
|
|
147
|
+
/// Enable per-request HTTP tracing (tower-http `TraceLayer`)
|
|
148
|
+
pub enable_http_trace: bool,
|
|
146
149
|
/// Dependency injection container (requires 'di' feature)
|
|
147
150
|
#[cfg(feature = "di")]
|
|
148
151
|
pub di_container: Option<std::sync::Arc<spikard_core::di::DependencyContainer>>,
|
|
@@ -154,10 +157,10 @@ impl Default for ServerConfig {
|
|
|
154
157
|
host: "127.0.0.1".to_string(),
|
|
155
158
|
port: 8000,
|
|
156
159
|
workers: 1,
|
|
157
|
-
enable_request_id:
|
|
160
|
+
enable_request_id: false,
|
|
158
161
|
max_body_size: Some(10 * 1024 * 1024),
|
|
159
|
-
request_timeout:
|
|
160
|
-
compression:
|
|
162
|
+
request_timeout: None,
|
|
163
|
+
compression: None,
|
|
161
164
|
rate_limit: None,
|
|
162
165
|
jwt_auth: None,
|
|
163
166
|
api_key_auth: None,
|
|
@@ -165,8 +168,10 @@ impl Default for ServerConfig {
|
|
|
165
168
|
graceful_shutdown: true,
|
|
166
169
|
shutdown_timeout: 30,
|
|
167
170
|
openapi: None,
|
|
171
|
+
jsonrpc: None,
|
|
168
172
|
lifecycle_hooks: None,
|
|
169
173
|
background_tasks: BackgroundTaskConfig::default(),
|
|
174
|
+
enable_http_trace: false,
|
|
170
175
|
#[cfg(feature = "di")]
|
|
171
176
|
di_container: None,
|
|
172
177
|
}
|
|
@@ -256,6 +261,12 @@ impl ServerConfigBuilder {
|
|
|
256
261
|
self
|
|
257
262
|
}
|
|
258
263
|
|
|
264
|
+
/// Enable or disable per-request HTTP tracing (tower-http `TraceLayer`)
|
|
265
|
+
pub fn enable_http_trace(mut self, enable: bool) -> Self {
|
|
266
|
+
self.config.enable_http_trace = enable;
|
|
267
|
+
self
|
|
268
|
+
}
|
|
269
|
+
|
|
259
270
|
/// Set maximum request body size in bytes (None = unlimited, not recommended)
|
|
260
271
|
pub fn max_body_size(mut self, size: Option<usize>) -> Self {
|
|
261
272
|
self.config.max_body_size = size;
|
|
@@ -322,6 +333,12 @@ impl ServerConfigBuilder {
|
|
|
322
333
|
self
|
|
323
334
|
}
|
|
324
335
|
|
|
336
|
+
/// Set JSON-RPC configuration
|
|
337
|
+
pub fn jsonrpc(mut self, jsonrpc: Option<crate::jsonrpc::JsonRpcConfig>) -> Self {
|
|
338
|
+
self.config.jsonrpc = jsonrpc;
|
|
339
|
+
self
|
|
340
|
+
}
|
|
341
|
+
|
|
325
342
|
/// Set lifecycle hooks for request/response processing
|
|
326
343
|
pub fn lifecycle_hooks(mut self, hooks: Option<std::sync::Arc<LifecycleHooks>>) -> Self {
|
|
327
344
|
self.config.lifecycle_hooks = hooks;
|
|
@@ -360,24 +377,16 @@ impl ServerConfigBuilder {
|
|
|
360
377
|
|
|
361
378
|
let key_str = key.into();
|
|
362
379
|
|
|
363
|
-
// Get or create DI container (mutable)
|
|
364
380
|
let container = if let Some(container) = self.config.di_container.take() {
|
|
365
|
-
|
|
366
|
-
Arc::try_unwrap(container).unwrap_or_else(|_arc| {
|
|
367
|
-
// If we can't unwrap, we lose existing dependencies
|
|
368
|
-
// This is a fallback that shouldn't happen in normal builder usage (linear chaining)
|
|
369
|
-
DependencyContainer::new()
|
|
370
|
-
})
|
|
381
|
+
Arc::try_unwrap(container).unwrap_or_else(|_arc| DependencyContainer::new())
|
|
371
382
|
} else {
|
|
372
383
|
DependencyContainer::new()
|
|
373
384
|
};
|
|
374
385
|
|
|
375
386
|
let mut container = container;
|
|
376
387
|
|
|
377
|
-
// Create ValueDependency
|
|
378
388
|
let dep = ValueDependency::new(key_str.clone(), value);
|
|
379
389
|
|
|
380
|
-
// Register (panic on error for builder pattern)
|
|
381
390
|
container
|
|
382
391
|
.register(key_str, Arc::new(dep))
|
|
383
392
|
.expect("Failed to register dependency");
|
|
@@ -433,7 +442,6 @@ impl ServerConfigBuilder {
|
|
|
433
442
|
|
|
434
443
|
let key_str = key.into();
|
|
435
444
|
|
|
436
|
-
// Get or create DI container (mutable)
|
|
437
445
|
let container = if let Some(container) = self.config.di_container.take() {
|
|
438
446
|
Arc::try_unwrap(container).unwrap_or_else(|_| DependencyContainer::new())
|
|
439
447
|
} else {
|
|
@@ -442,10 +450,8 @@ impl ServerConfigBuilder {
|
|
|
442
450
|
|
|
443
451
|
let mut container = container;
|
|
444
452
|
|
|
445
|
-
// Clone factory for the closure
|
|
446
453
|
let factory_clone = factory.clone();
|
|
447
454
|
|
|
448
|
-
// Create FactoryDependency using builder
|
|
449
455
|
let dep = FactoryDependency::builder(key_str.clone())
|
|
450
456
|
.factory(
|
|
451
457
|
move |_req: &axum::http::Request<()>,
|
|
@@ -501,7 +507,6 @@ impl ServerConfigBuilder {
|
|
|
501
507
|
|
|
502
508
|
let key = dependency.key().to_string();
|
|
503
509
|
|
|
504
|
-
// Get or create DI container (mutable)
|
|
505
510
|
let container = if let Some(container) = self.config.di_container.take() {
|
|
506
511
|
Arc::try_unwrap(container).unwrap_or_else(|_| DependencyContainer::new())
|
|
507
512
|
} else {
|
|
@@ -115,6 +115,11 @@ impl HookRegistry {
|
|
|
115
115
|
#[cfg(test)]
|
|
116
116
|
mod tests {
|
|
117
117
|
use super::*;
|
|
118
|
+
use crate::lifecycle::HookResult;
|
|
119
|
+
use axum::body::Body;
|
|
120
|
+
use axum::http::{Request, Response, StatusCode};
|
|
121
|
+
use std::future::Future;
|
|
122
|
+
use std::pin::Pin;
|
|
118
123
|
|
|
119
124
|
#[test]
|
|
120
125
|
fn test_error_messages() {
|
|
@@ -146,4 +151,80 @@ mod tests {
|
|
|
146
151
|
let deser_err = error::deserialize_failed("response", "malformed");
|
|
147
152
|
assert!(deser_err.contains("response"));
|
|
148
153
|
}
|
|
154
|
+
|
|
155
|
+
#[tokio::test]
|
|
156
|
+
async fn serial_extract_body_roundtrips_bytes() {
|
|
157
|
+
let body = Body::from("hello");
|
|
158
|
+
let bytes = serial::extract_body(body).await.expect("extract body");
|
|
159
|
+
assert_eq!(&bytes[..], b"hello");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
#[test]
|
|
163
|
+
fn serial_parse_json_handles_empty_valid_and_invalid_json() {
|
|
164
|
+
let empty = serial::parse_json(&[]).expect("parse empty");
|
|
165
|
+
assert_eq!(empty, serde_json::Value::Null);
|
|
166
|
+
|
|
167
|
+
let valid = serial::parse_json(br#"{"ok":true}"#).expect("parse json");
|
|
168
|
+
assert_eq!(valid["ok"], true);
|
|
169
|
+
|
|
170
|
+
let invalid = serial::parse_json(b"not-json").expect("parse fallback");
|
|
171
|
+
assert_eq!(invalid, serde_json::Value::String("not-json".to_string()));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
#[test]
|
|
175
|
+
fn hook_registry_registers_all_hooks_via_callback() {
|
|
176
|
+
struct NoopHook {
|
|
177
|
+
hook_name: String,
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
impl LifecycleHook<Request<Body>, Response<Body>> for NoopHook {
|
|
181
|
+
fn name(&self) -> &str {
|
|
182
|
+
&self.hook_name
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
fn execute_request<'a>(
|
|
186
|
+
&'a self,
|
|
187
|
+
req: Request<Body>,
|
|
188
|
+
) -> Pin<Box<dyn Future<Output = Result<HookResult<Request<Body>, Response<Body>>, String>> + Send + 'a>>
|
|
189
|
+
{
|
|
190
|
+
Box::pin(async move { Ok(HookResult::Continue(req)) })
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
fn execute_response<'a>(
|
|
194
|
+
&'a self,
|
|
195
|
+
resp: Response<Body>,
|
|
196
|
+
) -> Pin<Box<dyn Future<Output = Result<HookResult<Response<Body>, Response<Body>>, String>> + Send + 'a>>
|
|
197
|
+
{
|
|
198
|
+
Box::pin(async move { Ok(HookResult::Continue(resp)) })
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let mut hooks = HttpLifecycleHooks::new();
|
|
203
|
+
assert!(hooks.is_empty());
|
|
204
|
+
|
|
205
|
+
let hook_list: Vec<Arc<dyn LifecycleHook<Request<Body>, Response<Body>>>> = vec![
|
|
206
|
+
Arc::new(NoopHook {
|
|
207
|
+
hook_name: "one".to_string(),
|
|
208
|
+
}),
|
|
209
|
+
Arc::new(NoopHook {
|
|
210
|
+
hook_name: "two".to_string(),
|
|
211
|
+
}),
|
|
212
|
+
];
|
|
213
|
+
|
|
214
|
+
HookRegistry::register_from_list(&mut hooks, hook_list, "on_request", |hooks, hook| {
|
|
215
|
+
hooks.add_on_request(hook);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
let dbg = format!("{:?}", hooks);
|
|
219
|
+
assert!(dbg.contains("on_request_count"));
|
|
220
|
+
assert!(dbg.contains("2"));
|
|
221
|
+
|
|
222
|
+
let req = Request::builder().body(Body::empty()).unwrap();
|
|
223
|
+
let result = futures::executor::block_on(hooks.execute_on_request(req)).expect("hook run");
|
|
224
|
+
assert!(matches!(result, HookResult::Continue(_)));
|
|
225
|
+
|
|
226
|
+
let resp = Response::builder().status(StatusCode::OK).body(Body::empty()).unwrap();
|
|
227
|
+
let resp = futures::executor::block_on(hooks.execute_on_response(resp)).expect("hook run");
|
|
228
|
+
assert_eq!(resp.status(), StatusCode::OK);
|
|
229
|
+
}
|
|
149
230
|
}
|