spikard 0.3.2 → 0.3.4
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 +360 -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 +58 -58
- 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
- data/vendor/spikard-core/Cargo.toml +40 -40
- data/vendor/spikard-core/src/bindings/mod.rs +3 -3
- data/vendor/spikard-core/src/bindings/response.rs +133 -133
- data/vendor/spikard-core/src/debug.rs +63 -63
- data/vendor/spikard-core/src/di/container.rs +726 -726
- data/vendor/spikard-core/src/di/dependency.rs +273 -273
- data/vendor/spikard-core/src/di/error.rs +118 -118
- data/vendor/spikard-core/src/di/factory.rs +538 -538
- data/vendor/spikard-core/src/di/graph.rs +545 -545
- data/vendor/spikard-core/src/di/mod.rs +192 -192
- data/vendor/spikard-core/src/di/resolved.rs +411 -411
- data/vendor/spikard-core/src/di/value.rs +283 -283
- data/vendor/spikard-core/src/http.rs +153 -153
- data/vendor/spikard-core/src/lib.rs +28 -28
- data/vendor/spikard-core/src/lifecycle.rs +422 -422
- data/vendor/spikard-core/src/parameters.rs +719 -719
- data/vendor/spikard-core/src/problem.rs +310 -310
- data/vendor/spikard-core/src/request_data.rs +189 -189
- data/vendor/spikard-core/src/router.rs +249 -249
- data/vendor/spikard-core/src/schema_registry.rs +183 -183
- data/vendor/spikard-core/src/type_hints.rs +304 -304
- data/vendor/spikard-core/src/validation.rs +699 -699
- data/vendor/spikard-http/Cargo.toml +58 -58
- data/vendor/spikard-http/src/auth.rs +247 -247
- data/vendor/spikard-http/src/background.rs +249 -249
- data/vendor/spikard-http/src/bindings/mod.rs +3 -3
- data/vendor/spikard-http/src/bindings/response.rs +1 -1
- data/vendor/spikard-http/src/body_metadata.rs +8 -8
- data/vendor/spikard-http/src/cors.rs +490 -490
- data/vendor/spikard-http/src/debug.rs +63 -63
- data/vendor/spikard-http/src/di_handler.rs +423 -423
- data/vendor/spikard-http/src/handler_response.rs +190 -190
- data/vendor/spikard-http/src/handler_trait.rs +228 -228
- data/vendor/spikard-http/src/handler_trait_tests.rs +284 -284
- data/vendor/spikard-http/src/lib.rs +529 -529
- data/vendor/spikard-http/src/lifecycle/adapter.rs +149 -149
- data/vendor/spikard-http/src/lifecycle.rs +428 -428
- data/vendor/spikard-http/src/middleware/mod.rs +285 -285
- data/vendor/spikard-http/src/middleware/multipart.rs +86 -86
- data/vendor/spikard-http/src/middleware/urlencoded.rs +147 -147
- data/vendor/spikard-http/src/middleware/validation.rs +287 -287
- data/vendor/spikard-http/src/openapi/mod.rs +309 -309
- data/vendor/spikard-http/src/openapi/parameter_extraction.rs +190 -190
- data/vendor/spikard-http/src/openapi/schema_conversion.rs +308 -308
- data/vendor/spikard-http/src/openapi/spec_generation.rs +195 -195
- data/vendor/spikard-http/src/parameters.rs +1 -1
- data/vendor/spikard-http/src/problem.rs +1 -1
- data/vendor/spikard-http/src/query_parser.rs +369 -369
- data/vendor/spikard-http/src/response.rs +399 -399
- data/vendor/spikard-http/src/router.rs +1 -1
- data/vendor/spikard-http/src/schema_registry.rs +1 -1
- data/vendor/spikard-http/src/server/handler.rs +80 -80
- data/vendor/spikard-http/src/server/lifecycle_execution.rs +98 -98
- data/vendor/spikard-http/src/server/mod.rs +805 -805
- data/vendor/spikard-http/src/server/request_extraction.rs +119 -119
- data/vendor/spikard-http/src/sse.rs +447 -447
- data/vendor/spikard-http/src/testing/form.rs +14 -14
- data/vendor/spikard-http/src/testing/multipart.rs +60 -60
- data/vendor/spikard-http/src/testing/test_client.rs +285 -285
- data/vendor/spikard-http/src/testing.rs +377 -377
- data/vendor/spikard-http/src/type_hints.rs +1 -1
- data/vendor/spikard-http/src/validation.rs +1 -1
- data/vendor/spikard-http/src/websocket.rs +324 -324
- data/vendor/spikard-rb/Cargo.toml +42 -42
- data/vendor/spikard-rb/build.rs +8 -8
- data/vendor/spikard-rb/src/background.rs +63 -63
- data/vendor/spikard-rb/src/config.rs +294 -294
- data/vendor/spikard-rb/src/conversion.rs +392 -392
- data/vendor/spikard-rb/src/di.rs +409 -409
- data/vendor/spikard-rb/src/handler.rs +534 -534
- data/vendor/spikard-rb/src/lib.rs +2020 -2020
- data/vendor/spikard-rb/src/lifecycle.rs +267 -267
- data/vendor/spikard-rb/src/server.rs +283 -283
- data/vendor/spikard-rb/src/sse.rs +231 -231
- data/vendor/spikard-rb/src/test_client.rs +404 -404
- data/vendor/spikard-rb/src/test_sse.rs +143 -143
- data/vendor/spikard-rb/src/test_websocket.rs +221 -221
- data/vendor/spikard-rb/src/websocket.rs +233 -233
- metadata +1 -1
data/lib/spikard/sse.rb
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Spikard
|
|
4
|
-
# Represents a Server-Sent Event.
|
|
5
|
-
#
|
|
6
|
-
# @!attribute [rw] data
|
|
7
|
-
# @return [Hash] Event data (will be JSON serialized)
|
|
8
|
-
# @!attribute [rw] event_type
|
|
9
|
-
# @return [String, nil] Optional event type
|
|
10
|
-
# @!attribute [rw] id
|
|
11
|
-
# @return [String, nil] Optional event ID for client reconnection support
|
|
12
|
-
# @!attribute [rw] retry_ms
|
|
13
|
-
# @return [Integer, nil] Optional retry timeout in milliseconds
|
|
14
|
-
class SseEvent
|
|
15
|
-
attr_accessor :data, :event_type, :id, :retry_ms
|
|
16
|
-
|
|
17
|
-
# Create a new SSE event.
|
|
18
|
-
#
|
|
19
|
-
# @param data [Hash] Event data (will be JSON serialized)
|
|
20
|
-
# @param event_type [String, nil] Optional event type
|
|
21
|
-
# @param id [String, nil] Optional event ID for client reconnection support
|
|
22
|
-
# @param retry_ms [Integer, nil] Optional retry timeout in milliseconds
|
|
23
|
-
def initialize(data:, event_type: nil, id: nil, retry_ms: nil)
|
|
24
|
-
@data = data
|
|
25
|
-
@event_type = event_type
|
|
26
|
-
@id = id
|
|
27
|
-
@retry_ms = retry_ms
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Convert to hash for JSON serialization.
|
|
31
|
-
#
|
|
32
|
-
# @return [Hash] Hash representation of the event
|
|
33
|
-
def to_h
|
|
34
|
-
{
|
|
35
|
-
data: @data,
|
|
36
|
-
event_type: @event_type,
|
|
37
|
-
id: @id,
|
|
38
|
-
retry: @retry_ms
|
|
39
|
-
}.compact
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Base class for SSE event producers.
|
|
44
|
-
#
|
|
45
|
-
# Implement this class to generate Server-Sent Events.
|
|
46
|
-
#
|
|
47
|
-
# @example
|
|
48
|
-
# class NotificationProducer < Spikard::SseEventProducer
|
|
49
|
-
# def initialize
|
|
50
|
-
# @count = 0
|
|
51
|
-
# end
|
|
52
|
-
#
|
|
53
|
-
# def next_event
|
|
54
|
-
# sleep 1 # Wait 1 second between events
|
|
55
|
-
#
|
|
56
|
-
# return nil if @count >= 10 # End stream after 10 events
|
|
57
|
-
#
|
|
58
|
-
# event = Spikard::SseEvent.new(
|
|
59
|
-
# data: { message: "Notification #{@count}" },
|
|
60
|
-
# event_type: 'notification',
|
|
61
|
-
# id: @count.to_s
|
|
62
|
-
# )
|
|
63
|
-
# @count += 1
|
|
64
|
-
# event
|
|
65
|
-
# end
|
|
66
|
-
#
|
|
67
|
-
# def on_connect
|
|
68
|
-
# puts "Client connected to SSE stream"
|
|
69
|
-
# end
|
|
70
|
-
#
|
|
71
|
-
# def on_disconnect
|
|
72
|
-
# puts "Client disconnected from SSE stream"
|
|
73
|
-
# end
|
|
74
|
-
# end
|
|
75
|
-
#
|
|
76
|
-
# app = Spikard::App.new
|
|
77
|
-
#
|
|
78
|
-
# app.sse('/notifications') do
|
|
79
|
-
# NotificationProducer.new
|
|
80
|
-
# end
|
|
81
|
-
#
|
|
82
|
-
# app.run
|
|
83
|
-
class SseEventProducer
|
|
84
|
-
# Generate the next event.
|
|
85
|
-
#
|
|
86
|
-
# This method is called repeatedly to produce the event stream.
|
|
87
|
-
#
|
|
88
|
-
# @return [SseEvent, nil] SseEvent when an event is ready, or nil to end the stream.
|
|
89
|
-
def next_event
|
|
90
|
-
raise NotImplementedError, "#{self.class.name} must implement #next_event"
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Called when a client connects to the SSE endpoint.
|
|
94
|
-
#
|
|
95
|
-
# Override this method to perform initialization when a client connects.
|
|
96
|
-
#
|
|
97
|
-
# @return [void]
|
|
98
|
-
def on_connect
|
|
99
|
-
# Optional hook - default implementation does nothing
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# Called when a client disconnects from the SSE endpoint.
|
|
103
|
-
#
|
|
104
|
-
# Override this method to perform cleanup when a client disconnects.
|
|
105
|
-
#
|
|
106
|
-
# @return [void]
|
|
107
|
-
def on_disconnect
|
|
108
|
-
# Optional hook - default implementation does nothing
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spikard
|
|
4
|
+
# Represents a Server-Sent Event.
|
|
5
|
+
#
|
|
6
|
+
# @!attribute [rw] data
|
|
7
|
+
# @return [Hash] Event data (will be JSON serialized)
|
|
8
|
+
# @!attribute [rw] event_type
|
|
9
|
+
# @return [String, nil] Optional event type
|
|
10
|
+
# @!attribute [rw] id
|
|
11
|
+
# @return [String, nil] Optional event ID for client reconnection support
|
|
12
|
+
# @!attribute [rw] retry_ms
|
|
13
|
+
# @return [Integer, nil] Optional retry timeout in milliseconds
|
|
14
|
+
class SseEvent
|
|
15
|
+
attr_accessor :data, :event_type, :id, :retry_ms
|
|
16
|
+
|
|
17
|
+
# Create a new SSE event.
|
|
18
|
+
#
|
|
19
|
+
# @param data [Hash] Event data (will be JSON serialized)
|
|
20
|
+
# @param event_type [String, nil] Optional event type
|
|
21
|
+
# @param id [String, nil] Optional event ID for client reconnection support
|
|
22
|
+
# @param retry_ms [Integer, nil] Optional retry timeout in milliseconds
|
|
23
|
+
def initialize(data:, event_type: nil, id: nil, retry_ms: nil)
|
|
24
|
+
@data = data
|
|
25
|
+
@event_type = event_type
|
|
26
|
+
@id = id
|
|
27
|
+
@retry_ms = retry_ms
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Convert to hash for JSON serialization.
|
|
31
|
+
#
|
|
32
|
+
# @return [Hash] Hash representation of the event
|
|
33
|
+
def to_h
|
|
34
|
+
{
|
|
35
|
+
data: @data,
|
|
36
|
+
event_type: @event_type,
|
|
37
|
+
id: @id,
|
|
38
|
+
retry: @retry_ms
|
|
39
|
+
}.compact
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Base class for SSE event producers.
|
|
44
|
+
#
|
|
45
|
+
# Implement this class to generate Server-Sent Events.
|
|
46
|
+
#
|
|
47
|
+
# @example
|
|
48
|
+
# class NotificationProducer < Spikard::SseEventProducer
|
|
49
|
+
# def initialize
|
|
50
|
+
# @count = 0
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
# def next_event
|
|
54
|
+
# sleep 1 # Wait 1 second between events
|
|
55
|
+
#
|
|
56
|
+
# return nil if @count >= 10 # End stream after 10 events
|
|
57
|
+
#
|
|
58
|
+
# event = Spikard::SseEvent.new(
|
|
59
|
+
# data: { message: "Notification #{@count}" },
|
|
60
|
+
# event_type: 'notification',
|
|
61
|
+
# id: @count.to_s
|
|
62
|
+
# )
|
|
63
|
+
# @count += 1
|
|
64
|
+
# event
|
|
65
|
+
# end
|
|
66
|
+
#
|
|
67
|
+
# def on_connect
|
|
68
|
+
# puts "Client connected to SSE stream"
|
|
69
|
+
# end
|
|
70
|
+
#
|
|
71
|
+
# def on_disconnect
|
|
72
|
+
# puts "Client disconnected from SSE stream"
|
|
73
|
+
# end
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
76
|
+
# app = Spikard::App.new
|
|
77
|
+
#
|
|
78
|
+
# app.sse('/notifications') do
|
|
79
|
+
# NotificationProducer.new
|
|
80
|
+
# end
|
|
81
|
+
#
|
|
82
|
+
# app.run
|
|
83
|
+
class SseEventProducer
|
|
84
|
+
# Generate the next event.
|
|
85
|
+
#
|
|
86
|
+
# This method is called repeatedly to produce the event stream.
|
|
87
|
+
#
|
|
88
|
+
# @return [SseEvent, nil] SseEvent when an event is ready, or nil to end the stream.
|
|
89
|
+
def next_event
|
|
90
|
+
raise NotImplementedError, "#{self.class.name} must implement #next_event"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Called when a client connects to the SSE endpoint.
|
|
94
|
+
#
|
|
95
|
+
# Override this method to perform initialization when a client connects.
|
|
96
|
+
#
|
|
97
|
+
# @return [void]
|
|
98
|
+
def on_connect
|
|
99
|
+
# Optional hook - default implementation does nothing
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Called when a client disconnects from the SSE endpoint.
|
|
103
|
+
#
|
|
104
|
+
# Override this method to perform cleanup when a client disconnects.
|
|
105
|
+
#
|
|
106
|
+
# @return [void]
|
|
107
|
+
def on_disconnect
|
|
108
|
+
# Optional hook - default implementation does nothing
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Spikard
|
|
4
|
-
# Represents a streaming HTTP response made of chunks produced lazily.
|
|
5
|
-
class StreamingResponse
|
|
6
|
-
attr_reader :stream, :status_code, :headers, :native_response
|
|
7
|
-
|
|
8
|
-
def initialize(stream, status_code: 200, headers: nil)
|
|
9
|
-
unless stream.respond_to?(:next) || stream.respond_to?(:each)
|
|
10
|
-
raise ArgumentError, 'StreamingResponse requires an object responding to #next or #each'
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
@stream = stream.respond_to?(:to_enum) ? stream.to_enum : stream
|
|
14
|
-
@status_code = Integer(status_code || 200)
|
|
15
|
-
header_hash = headers || {}
|
|
16
|
-
@headers = header_hash.each_with_object({}) do |(key, value), memo|
|
|
17
|
-
memo[String(key)] = String(value)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
rebuild_native!
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def to_native_response
|
|
24
|
-
@native_response
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
def rebuild_native!
|
|
30
|
-
ensure_native!
|
|
31
|
-
@native_response = Spikard::Native.build_streaming_response(@stream, @status_code, @headers)
|
|
32
|
-
return unless @native_response
|
|
33
|
-
|
|
34
|
-
@status_code = @native_response.status_code
|
|
35
|
-
@headers = @native_response.headers
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def ensure_native!
|
|
39
|
-
return if defined?(Spikard::Native) && Spikard::Native.respond_to?(:build_streaming_response)
|
|
40
|
-
|
|
41
|
-
raise 'Spikard native extension is not loaded'
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spikard
|
|
4
|
+
# Represents a streaming HTTP response made of chunks produced lazily.
|
|
5
|
+
class StreamingResponse
|
|
6
|
+
attr_reader :stream, :status_code, :headers, :native_response
|
|
7
|
+
|
|
8
|
+
def initialize(stream, status_code: 200, headers: nil)
|
|
9
|
+
unless stream.respond_to?(:next) || stream.respond_to?(:each)
|
|
10
|
+
raise ArgumentError, 'StreamingResponse requires an object responding to #next or #each'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
@stream = stream.respond_to?(:to_enum) ? stream.to_enum : stream
|
|
14
|
+
@status_code = Integer(status_code || 200)
|
|
15
|
+
header_hash = headers || {}
|
|
16
|
+
@headers = header_hash.each_with_object({}) do |(key, value), memo|
|
|
17
|
+
memo[String(key)] = String(value)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
rebuild_native!
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_native_response
|
|
24
|
+
@native_response
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def rebuild_native!
|
|
30
|
+
ensure_native!
|
|
31
|
+
@native_response = Spikard::Native.build_streaming_response(@stream, @status_code, @headers)
|
|
32
|
+
return unless @native_response
|
|
33
|
+
|
|
34
|
+
@status_code = @native_response.status_code
|
|
35
|
+
@headers = @native_response.headers
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ensure_native!
|
|
39
|
+
return if defined?(Spikard::Native) && Spikard::Native.respond_to?(:build_streaming_response)
|
|
40
|
+
|
|
41
|
+
raise 'Spikard native extension is not loaded'
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|