aboutsummaryrefslogtreecommitdiffstats
path: root/lib/plum/stream_utils.rb
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2015-08-11 21:10:33 +0900
committerKazuki Yamaguchi <k@rhe.jp>2015-08-11 21:10:33 +0900
commit72fc8863a315916237a5e3141432c8926783c2bf (patch)
treeea88e6277bacc187df3aac9de46a9d9157669039 /lib/plum/stream_utils.rb
parent45517dac41ca3ae0575a936576b7cc6828458244 (diff)
downloadplum-72fc8863a315916237a5e3141432c8926783c2bf.tar.gz
rename StreamHelper to StreamUtils
Diffstat (limited to 'lib/plum/stream_utils.rb')
-rw-r--r--lib/plum/stream_utils.rb58
1 files changed, 58 insertions, 0 deletions
diff --git a/lib/plum/stream_utils.rb b/lib/plum/stream_utils.rb
new file mode 100644
index 0000000..0c4f4a6
--- /dev/null
+++ b/lib/plum/stream_utils.rb
@@ -0,0 +1,58 @@
+using Plum::BinaryString
+
+module Plum
+ module StreamUtils
+ # Responds to HTTP request.
+ #
+ # @param headers [Hash<String, String>] The response headers.
+ # @param body [String, IO] The response body.
+ def respond(headers, body = nil, end_stream: true) # TODO: priority, padding
+ if body
+ send_headers(headers, end_stream: false)
+ send_data(body, end_stream: end_stream)
+ else
+ send_headers(headers, end_stream: end_stream)
+ end
+ end
+
+ # Reserves a stream to server push. Sends PUSH_STREAM and create new stream.
+ #
+ # @param headers [Hash<String, String>] The *request* headers. It must contain all of them: ':authority', ':method', ':scheme' and ':path'.
+ # @return [Stream] The stream to send push response.
+ def promise(headers)
+ stream = @connection.reserve_stream(weight: self.weight + 1, parent: self)
+ encoded = @connection.hpack_encoder.encode(headers)
+ original = Frame.push_promise(id, stream.id, encoded, :end_headers)
+ original.split_headers(@connection.remote_settings[:max_frame_size]).each do |frame|
+ send frame
+ end
+ stream
+ end
+
+ private
+ def send_headers(headers, end_stream:)
+ max = @connection.remote_settings[:max_frame_size]
+ encoded = @connection.hpack_encoder.encode(headers)
+ original_frame = Frame.headers(id, encoded, :end_headers, (end_stream && :end_stream || nil))
+ original_frame.split_headers(max).each do |frame|
+ send frame
+ end
+ @state = :half_closed_local if end_stream
+ end
+
+ def send_data(data, end_stream: true)
+ max = @connection.remote_settings[:max_frame_size]
+ if data.is_a?(IO)
+ while !data.eof? && fragment = data.readpartial(max)
+ send Frame.data(id, fragment, (end_stream && data.eof? && :end_stream))
+ end
+ else
+ original = Frame.data(id, data, (end_stream && :end_stream))
+ original.split_data(max).each do |frame|
+ send frame
+ end
+ end
+ @state = :half_closed_local if end_stream
+ end
+ end
+end