From e623d67b0d6cd267ee5febe57bae8720ad3e85f4 Mon Sep 17 00:00:00 2001 From: Piotr Boniecki Date: Wed, 22 Jan 2020 14:22:20 +0100 Subject: [PATCH] Fix parser so it properly parses headers ..when they are returned in parts Resolves: #589 --- lib/http/response/parser.rb | 26 ++++++++++++---- spec/lib/http/response/parser_spec.rb | 45 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 spec/lib/http/response/parser_spec.rb diff --git a/lib/http/response/parser.rb b/lib/http/response/parser.rb index 19989d59..88c358ad 100644 --- a/lib/http/response/parser.rb +++ b/lib/http/response/parser.rb @@ -49,14 +49,17 @@ def status_code # def on_header_field(_response, field) - @field = field + append_header if @reading_header_value + @field << field end def on_header_value(_response, value) - @headers.add(@field, value) if @field + @reading_header_value = true + @field_value << value end def on_headers_complete(_reposse) + append_header if @reading_header_value @finished[:headers] = true end @@ -89,15 +92,26 @@ def on_message_complete(_response) def reset @state.reset! - @finished = Hash.new(false) - @headers = HTTP::Headers.new - @field = nil - @chunk = nil + @finished = Hash.new(false) + @headers = HTTP::Headers.new + @reading_header_value = false + @field = +"" + @field_value = +"" + @chunk = nil end def finished? @finished[:message] end + + private + + def append_header + @headers.add(@field, @field_value) + @reading_header_value = false + @field_value = +"" + @field = +"" + end end end end diff --git a/spec/lib/http/response/parser_spec.rb b/spec/lib/http/response/parser_spec.rb new file mode 100644 index 00000000..0772f343 --- /dev/null +++ b/spec/lib/http/response/parser_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +RSpec.describe HTTP::Response::Parser do + subject(:parser) { described_class.new } + let(:raw_response) do + "HTTP/1.1 200 OK\r\nContent-Length: 2\r\nContent-Type: application/json\r\nMyHeader: val\r\nEmptyHeader: \r\n\r\n{}" + end + let(:expected_headers) do + { + "Content-Length" => "2", + "Content-Type" => "application/json", + "MyHeader" => "val", + "EmptyHeader" => "" + } + end + let(:expected_body) { "{}" } + + before do + parts.each { |part| subject.add(part) } + end + + context "whole response in one part" do + let(:parts) { [raw_response] } + + it "parses headers" do + expect(subject.headers.to_h).to eq(expected_headers) + end + + it "parses body" do + expect(subject.read(expected_body.size)).to eq(expected_body) + end + end + + context "response in many parts" do + let(:parts) { raw_response.split(//) } + + it "parses headers" do + expect(subject.headers.to_h).to eq(expected_headers) + end + + it "parses body" do + expect(subject.read(expected_body.size)).to eq(expected_body) + end + end +end