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
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spikard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Na'aman Hirschfeld
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-12-01 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: websocket-client-simple
@@ -68,85 +67,8 @@ files:
68
67
  - lib/spikard/version.rb
69
68
  - lib/spikard/websocket.rb
70
69
  - sig/spikard.rbs
71
- - vendor/bundle/ruby/3.3.0/gems/diff-lcs-1.6.2/mise.toml
72
- - vendor/crates/spikard-core/Cargo.toml
73
- - vendor/crates/spikard-core/src/bindings/mod.rs
74
- - vendor/crates/spikard-core/src/bindings/response.rs
75
- - vendor/crates/spikard-core/src/debug.rs
76
- - vendor/crates/spikard-core/src/di/container.rs
77
- - vendor/crates/spikard-core/src/di/dependency.rs
78
- - vendor/crates/spikard-core/src/di/error.rs
79
- - vendor/crates/spikard-core/src/di/factory.rs
80
- - vendor/crates/spikard-core/src/di/graph.rs
81
- - vendor/crates/spikard-core/src/di/mod.rs
82
- - vendor/crates/spikard-core/src/di/resolved.rs
83
- - vendor/crates/spikard-core/src/di/value.rs
84
- - vendor/crates/spikard-core/src/http.rs
85
- - vendor/crates/spikard-core/src/lib.rs
86
- - vendor/crates/spikard-core/src/lifecycle.rs
87
- - vendor/crates/spikard-core/src/parameters.rs
88
- - vendor/crates/spikard-core/src/problem.rs
89
- - vendor/crates/spikard-core/src/request_data.rs
90
- - vendor/crates/spikard-core/src/router.rs
91
- - vendor/crates/spikard-core/src/schema_registry.rs
92
- - vendor/crates/spikard-core/src/type_hints.rs
93
- - vendor/crates/spikard-core/src/validation.rs
94
- - vendor/crates/spikard-http/Cargo.toml
95
- - vendor/crates/spikard-http/src/auth.rs
96
- - vendor/crates/spikard-http/src/background.rs
97
- - vendor/crates/spikard-http/src/bindings/mod.rs
98
- - vendor/crates/spikard-http/src/bindings/response.rs
99
- - vendor/crates/spikard-http/src/body_metadata.rs
100
- - vendor/crates/spikard-http/src/cors.rs
101
- - vendor/crates/spikard-http/src/debug.rs
102
- - vendor/crates/spikard-http/src/di_handler.rs
103
- - vendor/crates/spikard-http/src/handler_response.rs
104
- - vendor/crates/spikard-http/src/handler_trait.rs
105
- - vendor/crates/spikard-http/src/handler_trait_tests.rs
106
- - vendor/crates/spikard-http/src/lib.rs
107
- - vendor/crates/spikard-http/src/lifecycle.rs
108
- - vendor/crates/spikard-http/src/lifecycle/adapter.rs
109
- - vendor/crates/spikard-http/src/middleware/mod.rs
110
- - vendor/crates/spikard-http/src/middleware/multipart.rs
111
- - vendor/crates/spikard-http/src/middleware/urlencoded.rs
112
- - vendor/crates/spikard-http/src/middleware/validation.rs
113
- - vendor/crates/spikard-http/src/openapi/mod.rs
114
- - vendor/crates/spikard-http/src/openapi/parameter_extraction.rs
115
- - vendor/crates/spikard-http/src/openapi/schema_conversion.rs
116
- - vendor/crates/spikard-http/src/openapi/spec_generation.rs
117
- - vendor/crates/spikard-http/src/parameters.rs
118
- - vendor/crates/spikard-http/src/problem.rs
119
- - vendor/crates/spikard-http/src/query_parser.rs
120
- - vendor/crates/spikard-http/src/response.rs
121
- - vendor/crates/spikard-http/src/router.rs
122
- - vendor/crates/spikard-http/src/schema_registry.rs
123
- - vendor/crates/spikard-http/src/server/handler.rs
124
- - vendor/crates/spikard-http/src/server/lifecycle_execution.rs
125
- - vendor/crates/spikard-http/src/server/mod.rs
126
- - vendor/crates/spikard-http/src/server/request_extraction.rs
127
- - vendor/crates/spikard-http/src/sse.rs
128
- - vendor/crates/spikard-http/src/testing.rs
129
- - vendor/crates/spikard-http/src/testing/form.rs
130
- - vendor/crates/spikard-http/src/testing/multipart.rs
131
- - vendor/crates/spikard-http/src/testing/test_client.rs
132
- - vendor/crates/spikard-http/src/type_hints.rs
133
- - vendor/crates/spikard-http/src/validation.rs
134
- - vendor/crates/spikard-http/src/websocket.rs
135
- - vendor/crates/spikard-rb/Cargo.toml
136
- - vendor/crates/spikard-rb/build.rs
137
- - vendor/crates/spikard-rb/src/background.rs
138
- - vendor/crates/spikard-rb/src/config.rs
139
- - vendor/crates/spikard-rb/src/conversion.rs
140
- - vendor/crates/spikard-rb/src/di.rs
141
- - vendor/crates/spikard-rb/src/handler.rs
142
- - vendor/crates/spikard-rb/src/lib.rs
143
- - vendor/crates/spikard-rb/src/lifecycle.rs
144
- - vendor/crates/spikard-rb/src/server.rs
145
- - vendor/crates/spikard-rb/src/sse.rs
146
- - vendor/crates/spikard-rb/src/test_client.rs
147
- - vendor/crates/spikard-rb/src/test_sse.rs
148
- - vendor/crates/spikard-rb/src/test_websocket.rs
149
- - vendor/crates/spikard-rb/src/websocket.rs
70
+ - vendor/bundle/ruby/3.4.0/gems/diff-lcs-1.6.2/mise.toml
71
+ - vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.10.0/build/buildkitd.toml
150
72
  homepage: https://github.com/Goldziher/spikard
151
73
  licenses:
152
74
  - MIT
@@ -158,7 +80,6 @@ metadata:
158
80
  bug_tracker_uri: https://github.com/Goldziher/spikard/issues
159
81
  funding_uri: https://github.com/Goldziher/spikard
160
82
  rubygems_mfa_required: 'true'
161
- post_install_message:
162
83
  rdoc_options: []
163
84
  require_paths:
164
85
  - lib
@@ -173,8 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
94
  - !ruby/object:Gem::Version
174
95
  version: '0'
175
96
  requirements: []
176
- rubygems_version: 3.5.22
177
- signing_key:
97
+ rubygems_version: 3.6.9
178
98
  specification_version: 4
179
99
  summary: High-performance HTTP toolkit with Rust core and Ruby bindings
180
100
  test_files: []
@@ -1,40 +0,0 @@
1
- [package]
2
- name = "spikard-core"
3
- version.workspace = true
4
- edition.workspace = true
5
- authors.workspace = true
6
- license.workspace = true
7
- repository.workspace = true
8
- homepage.workspace = true
9
- description = "Shared transport-agnostic primitives for Spikard runtimes"
10
- keywords = ["http", "web", "framework", "validation", "middleware"]
11
- categories = ["web-programming::http-server", "web-programming", "development-tools"]
12
- documentation = "https://docs.rs/spikard-core"
13
- readme = "README.md"
14
-
15
- [dependencies]
16
- serde.workspace = true
17
- serde_json.workspace = true
18
- tracing.workspace = true
19
- anyhow = "1.0"
20
- jsonschema.workspace = true
21
- regex = "1"
22
- flate2 = "1.1"
23
- brotli = "8.0"
24
- http.workspace = true
25
- base64 = "0.22"
26
- serde_qs = "0.15"
27
- url = "2.5"
28
- jiff = "0.2"
29
- uuid = "1.18"
30
- indexmap = "2.12"
31
- tokio = { workspace = true, optional = true }
32
- bytes = { version = "1.11", optional = true }
33
- thiserror = { workspace = true, optional = true }
34
-
35
- [features]
36
- default = []
37
- di = ["dep:tokio", "dep:bytes", "dep:thiserror"]
38
-
39
- [dev-dependencies]
40
- tokio-test = "0.4"
@@ -1,3 +0,0 @@
1
- pub mod response;
2
-
3
- pub use response::{RawResponse, StaticAsset};
@@ -1,133 +0,0 @@
1
- use crate::CompressionConfig;
2
- use brotli::CompressorWriter;
3
- use flate2::Compression;
4
- use flate2::write::GzEncoder;
5
- use std::collections::HashMap;
6
- use std::io::Write;
7
-
8
- /// Minimal response container shared by bindings.
9
- #[derive(Clone, Debug)]
10
- pub struct RawResponse {
11
- pub status: u16,
12
- pub headers: HashMap<String, String>,
13
- pub body: Vec<u8>,
14
- }
15
-
16
- impl RawResponse {
17
- /// Construct a new response.
18
- pub fn new(status: u16, headers: HashMap<String, String>, body: Vec<u8>) -> Self {
19
- Self { status, headers, body }
20
- }
21
-
22
- /// Apply compression filters if the response qualifies.
23
- pub fn apply_compression(&mut self, request_headers: &HashMap<String, String>, compression: &CompressionConfig) {
24
- if self.body.is_empty() || self.status == 206 {
25
- return;
26
- }
27
- if self
28
- .headers
29
- .keys()
30
- .any(|key| key.eq_ignore_ascii_case("content-encoding"))
31
- {
32
- return;
33
- }
34
- if self.body.len() < compression.min_size {
35
- return;
36
- }
37
-
38
- let accept_encoding = header_value(request_headers, "Accept-Encoding").map(|value| value.to_ascii_lowercase());
39
- let accepts_brotli = accept_encoding
40
- .as_ref()
41
- .map(|value| value.contains("br"))
42
- .unwrap_or(false);
43
- if compression.brotli && accepts_brotli && self.try_compress_brotli(compression) {
44
- return;
45
- }
46
-
47
- let accepts_gzip = accept_encoding
48
- .as_ref()
49
- .map(|value| value.contains("gzip"))
50
- .unwrap_or(false);
51
- if compression.gzip && accepts_gzip {
52
- self.try_compress_gzip(compression);
53
- }
54
- }
55
-
56
- fn try_compress_brotli(&mut self, compression: &CompressionConfig) -> bool {
57
- let quality = compression.quality.min(11);
58
- let mut writer = CompressorWriter::new(Vec::new(), 4096, quality, 22);
59
- if writer.write_all(&self.body).is_err() || writer.flush().is_err() {
60
- return false;
61
- }
62
- let compressed = writer.into_inner();
63
- if compressed.is_empty() {
64
- return false;
65
- }
66
- self.finalize_encoded_body("br", compressed);
67
- true
68
- }
69
-
70
- fn try_compress_gzip(&mut self, compression: &CompressionConfig) -> bool {
71
- let mut encoder = GzEncoder::new(Vec::new(), Compression::new(compression.quality));
72
- if encoder.write_all(&self.body).is_err() {
73
- return false;
74
- }
75
- let compressed = encoder.finish().unwrap_or_else(|_| Vec::new());
76
- if compressed.is_empty() {
77
- return false;
78
- }
79
- self.finalize_encoded_body("gzip", compressed);
80
- true
81
- }
82
-
83
- fn finalize_encoded_body(&mut self, encoding: &str, compressed: Vec<u8>) {
84
- self.body = compressed;
85
- self.headers
86
- .insert("content-encoding".to_string(), encoding.to_string());
87
- self.headers.insert("vary".to_string(), "Accept-Encoding".to_string());
88
- self.headers
89
- .insert("content-length".to_string(), self.body.len().to_string());
90
- }
91
- }
92
-
93
- fn header_value<'a>(headers: &'a HashMap<String, String>, name: &str) -> Option<&'a str> {
94
- headers.iter().find_map(|(key, value)| {
95
- if key.eq_ignore_ascii_case(name) {
96
- Some(value.as_str())
97
- } else {
98
- None
99
- }
100
- })
101
- }
102
-
103
- /// Pre-rendered static asset produced by the CLI bundler.
104
- #[derive(Clone, Debug)]
105
- pub struct StaticAsset {
106
- pub route: String,
107
- pub headers: HashMap<String, String>,
108
- pub body: Vec<u8>,
109
- }
110
-
111
- impl StaticAsset {
112
- /// Build a response snapshot if the incoming request targets this asset.
113
- pub fn serve(&self, method: &str, normalized_path: &str) -> Option<RawResponse> {
114
- if !method.eq_ignore_ascii_case("GET") && !method.eq_ignore_ascii_case("HEAD") {
115
- return None;
116
- }
117
- if self.route != normalized_path {
118
- return None;
119
- }
120
-
121
- let mut headers = self.headers.clone();
122
- headers
123
- .entry("content-length".to_string())
124
- .or_insert_with(|| self.body.len().to_string());
125
- let body = if method.eq_ignore_ascii_case("HEAD") {
126
- Vec::new()
127
- } else {
128
- self.body.clone()
129
- };
130
-
131
- Some(RawResponse::new(200, headers, body))
132
- }
133
- }
@@ -1,63 +0,0 @@
1
- //! Debug logging utilities for spikard-http
2
- //!
3
- //! This module provides debug logging that can be enabled via:
4
- //! - Building in debug mode (cfg(debug_assertions))
5
- //! - Setting SPIKARD_DEBUG=1 environment variable
6
-
7
- use std::sync::atomic::{AtomicBool, Ordering};
8
-
9
- static DEBUG_ENABLED: AtomicBool = AtomicBool::new(false);
10
-
11
- /// Initialize debug logging based on environment and build mode
12
- pub fn init() {
13
- let enabled = cfg!(debug_assertions) || std::env::var("SPIKARD_DEBUG").is_ok() || std::env::var("DEBUG").is_ok();
14
-
15
- eprintln!(
16
- "[spikard-http::debug] init() called, cfg!(debug_assertions)={}, DEBUG={}, enabled={}",
17
- cfg!(debug_assertions),
18
- std::env::var("DEBUG").is_ok(),
19
- enabled
20
- );
21
-
22
- DEBUG_ENABLED.store(enabled, Ordering::Relaxed);
23
-
24
- if enabled {
25
- eprintln!("[spikard-http] Debug logging enabled");
26
- }
27
- }
28
-
29
- /// Check if debug logging is enabled
30
- #[inline]
31
- pub fn is_enabled() -> bool {
32
- DEBUG_ENABLED.load(Ordering::Relaxed)
33
- }
34
-
35
- /// Log a debug message if debugging is enabled
36
- #[macro_export]
37
- macro_rules! debug_log {
38
- ($($arg:tt)*) => {
39
- if $crate::debug::is_enabled() {
40
- eprintln!("[spikard-http] {}", format!($($arg)*));
41
- }
42
- };
43
- }
44
-
45
- /// Log a debug message with a specific module/component name
46
- #[macro_export]
47
- macro_rules! debug_log_module {
48
- ($module:expr, $($arg:tt)*) => {
49
- if $crate::debug::is_enabled() {
50
- eprintln!("[spikard-http::{}] {}", $module, format!($($arg)*));
51
- }
52
- };
53
- }
54
-
55
- /// Log a debug value with pretty-printing
56
- #[macro_export]
57
- macro_rules! debug_log_value {
58
- ($name:expr, $value:expr) => {
59
- if $crate::debug::is_enabled() {
60
- eprintln!("[spikard-http] {} = {:?}", $name, $value);
61
- }
62
- };
63
- }