diff --git a/http.gemspec b/http.gemspec index 2f1b3615..d097863c 100644 --- a/http.gemspec +++ b/http.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |gem| gem.required_ruby_version = ">= 2.2" - gem.add_runtime_dependency "http_parser.rb", "~> 0.6.0" + gem.add_runtime_dependency "http-parser", "~> 1.2.0" gem.add_runtime_dependency "http-form_data", ">= 2.0.0-pre2", "< 3" gem.add_runtime_dependency "http-cookie", "~> 1.0" gem.add_runtime_dependency "addressable", "~> 2.3" diff --git a/lib/http.rb b/lib/http.rb index a1338598..c430127a 100644 --- a/lib/http.rb +++ b/lib/http.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "http/parser" - require "http/errors" require "http/timeout/null" require "http/timeout/per_operation" diff --git a/lib/http/response/parser.rb b/lib/http/response/parser.rb index 743cd7a8..90e0d80a 100644 --- a/lib/http/response/parser.rb +++ b/lib/http/response/parser.rb @@ -1,41 +1,53 @@ # frozen_string_literal: true +require "http-parser" + module HTTP class Response class Parser attr_reader :headers def initialize - @parser = HTTP::Parser.new(self) + @state = HttpParser::Parser.new_instance { |i| i.type = :response } + @parser = HttpParser::Parser.new(self) + reset end def add(data) - @parser << data + @parser.parse(@state, data) end alias << add def headers? - !!@headers + @finished[:headers] end def http_version - @parser.http_version.join(".") + @state.http_version end def status_code - @parser.status_code + @state.http_status end # # HTTP::Parser callbacks # - def on_headers_complete(headers) - @headers = headers + def on_header_field(_response, field) + @field = field + end + + def on_header_value(_response, value) + @headers.add(@field, value) if @field + end + + def on_headers_complete(_reposse) + @finished[:headers] = true end - def on_body(chunk) + def on_body(_response, chunk) if @chunk @chunk << chunk else @@ -49,20 +61,21 @@ def chunk chunk end - def on_message_complete - @finished = true + def on_message_complete(_response) + @finished[:message] = true end def reset - @parser.reset! + @state.reset! - @finished = false - @headers = nil + @finished = Hash.new(false) + @headers = HTTP::Headers.new + @field = nil @chunk = nil end def finished? - @finished + @finished[:message] end end end diff --git a/spec/regression_specs.rb b/spec/regression_specs.rb index eae2b5a6..67fd46a2 100644 --- a/spec/regression_specs.rb +++ b/spec/regression_specs.rb @@ -14,4 +14,11 @@ expect { HTTP.get(google_uri).to_s }.not_to raise_error end end + + describe "#422" do + it "reads body when 200 OK response contains Upgrade header" do + res = HTTP.get("https://httpbin.org/response-headers?Upgrade=h2,h2c") + expect(res.parse(:json)).to include("Upgrade" => "h2,h2c") + end + end end