aboutsummaryrefslogtreecommitdiffstats
path: root/lib/plum/http_connection.rb
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2015-08-14 18:17:23 +0900
committerKazuki Yamaguchi <k@rhe.jp>2015-08-14 18:17:23 +0900
commit771d444bb5ddd3d49dfec874fd6ac1288bd9b9b3 (patch)
treee739ed14077b51fbba3ec0bf652f2566b40c52f0 /lib/plum/http_connection.rb
parentd56903896a08d68308341be00cbc9c2181c657e0 (diff)
downloadplum-771d444bb5ddd3d49dfec874fd6ac1288bd9b9b3.tar.gz
refactor
Diffstat (limited to 'lib/plum/http_connection.rb')
-rw-r--r--lib/plum/http_connection.rb78
1 files changed, 39 insertions, 39 deletions
diff --git a/lib/plum/http_connection.rb b/lib/plum/http_connection.rb
index e5e63f6..4ffea73 100644
--- a/lib/plum/http_connection.rb
+++ b/lib/plum/http_connection.rb
@@ -5,58 +5,56 @@ module Plum
def initialize(io, local_settings = {})
require "http/parser"
super
+ @_headers = nil
+ @_body = ""
@_http_parser = setup_parser
- @_upgrade_retry = false # After sent 426 (Upgrade Required)
end
private
+ def negotiate!
+ super
+ rescue ConnectionError
+ # Upgrade from HTTP/1.1
+ offset = @_http_parser << @buffer
+ @buffer.byteshift(offset)
+ end
+
def setup_parser
- headers = nil
- body = ""
parser = HTTP::Parser.new
- parser.on_message_begin = proc { }
- parser.on_headers_complete = proc {|_headers| headers = _headers }
- parser.on_body = proc {|chunk| body << chunk }
- parser.on_message_complete = proc do |env|
- # Upgrade from HTTP/1.1
- heads = headers.map {|n, v| [n.downcase, v] }.to_h
- connection = heads["connection"] || ""
- upgrade = heads["upgrade"] || ""
- settings = heads["http2-settings"]
+ parser.on_headers_complete = proc {|_headers|
+ @_headers = _headers.map {|n, v| [n.downcase, v] }.to_h
+ }
+ parser.on_body = proc {|chunk| @_body << chunk }
+ parser.on_message_complete = proc {|env|
+ connection = @_headers["connection"] || ""
+ upgrade = @_headers["upgrade"] || ""
+ settings = @_headers["http2-settings"]
if (connection.split(", ").sort == ["Upgrade", "HTTP2-Settings"].sort &&
upgrade.split(", ").include?("h2c") &&
settings != nil)
- respond_switching_protocol
- self.on(:negotiated) {
- _frame = Frame.new(type: :settings, stream_id: 0, payload: Base64.urlsafe_decode64(settings))
- receive_settings(_frame, send_ack: false) # HTTP2-Settings
- process_first_request(parser, heads, body)
- }
+ switch_protocol(settings)
else
respond_not_supported
close
end
- end
+ }
parser
end
- def negotiate!
- begin
- super
- rescue ConnectionError
- # Upgrade from HTTP/1.1
- offset = @_http_parser << @buffer
- @buffer.byteshift(offset)
- end
- end
+ def switch_protocol(settings)
+ self.on(:negotiated) {
+ _frame = Frame.new(type: :settings, stream_id: 0, payload: Base64.urlsafe_decode64(settings))
+ receive_settings(_frame, send_ack: false) # HTTP2-Settings
+ process_first_request
+ }
- def respond_switching_protocol
resp = ""
resp << "HTTP/1.1 101 Switching Protocols\r\n"
resp << "Connection: Upgrade\r\n"
resp << "Upgrade: h2c\r\n"
+ resp << "Server: plum/#{Plum::VERSION}\r\n"
resp << "\r\n"
io.write(resp)
@@ -69,23 +67,25 @@ module Plum
resp << "HTTP/1.1 505 HTTP Version Not Supported\r\n"
resp << "Content-Type: text/plain\r\n"
resp << "Content-Length: #{data.bytesize}\r\n"
+ resp << "Server: plum/#{Plum::VERSION}\r\n"
resp << "\r\n"
resp << data
io.write(resp)
end
- def process_first_request(parser, heads, dat)
- stream = new_stream(1)
- heads = heads.merge({ ":method" => parser.http_method,
- ":path" => parser.request_url,
- ":authority" => heads["host"] })
- .reject {|n, v| ["connection", "http2-settings", "upgrade", "host"].include?(n) }
+ def process_first_request
encoder = HPACK::Encoder.new(0, indexing: false) # don't pollute connection's HPACK context
- headers = Frame.headers(1, encoder.encode(heads), :end_headers) # stream ID is 1
- headers.split_headers(local_settings[:max_frame_size]).each {|hfrag| stream.receive_frame(hfrag) }
- data = Frame.data(1, dat, :end_stream)
- data.split_data(local_settings[:max_frame_size]).each {|dfrag| stream.receive_frame(dfrag) }
+ stream = new_stream(1)
+ max_frame_size = local_settings[:max_frame_size]
+ headers = @_headers.merge({ ":method" => @_http_parser.http_method,
+ ":path" => @_http_parser.request_url,
+ ":authority" => @_headers["host"] })
+ .reject {|n, v| ["connection", "http2-settings", "upgrade", "host"].include?(n) }
+
+ headers_s = Frame.headers(1, encoder.encode(headers), :end_headers).split_headers(max_frame_size) # stream ID is 1
+ data_s = Frame.data(1, @_body, :end_stream).split_data(max_frame_size)
+ (headers_s + data_s).each {|frag| stream.receive_frame(frag) }
end
end
end