diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2015-08-14 18:17:23 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2015-08-14 18:17:23 +0900 |
commit | 771d444bb5ddd3d49dfec874fd6ac1288bd9b9b3 (patch) | |
tree | e739ed14077b51fbba3ec0bf652f2566b40c52f0 /lib/plum/http_connection.rb | |
parent | d56903896a08d68308341be00cbc9c2181c657e0 (diff) | |
download | plum-771d444bb5ddd3d49dfec874fd6ac1288bd9b9b3.tar.gz |
refactor
Diffstat (limited to 'lib/plum/http_connection.rb')
-rw-r--r-- | lib/plum/http_connection.rb | 78 |
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 |