diff --git a/lib/protocol/http/headers.rb b/lib/protocol/http/headers.rb index 69e386b..0080458 100644 --- a/lib/protocol/http/headers.rb +++ b/lib/protocol/http/headers.rb @@ -64,13 +64,15 @@ def self.[] headers # Initialize the headers with the specified fields. # # @parameter fields [Array] An array of `[key, value]` pairs. - # @parameter indexed [Hash] A hash table of normalized headers, if available. - def initialize(fields = [], indexed = nil) + # @parameter tail [Integer | Nil] The index of the trailer start in the @fields array. + def initialize(fields = [], tail = nil, indexed: nil) @fields = fields - @indexed = indexed - # Marks where trailer start in the @fields array. - @tail = nil + # Marks where trailer start in the @fields array: + @tail = tail + + # The cached index of headers: + @indexed = nil end # Initialize a copy of the headers. @@ -86,8 +88,8 @@ def initialize_dup(other) # Clear all headers. def clear @fields.clear - @indexed = nil @tail = nil + @indexed = nil end # Flatten trailer into the headers, in-place. @@ -108,6 +110,9 @@ def flatten # @attribute [Array] An array of `[key, value]` pairs. attr :fields + # @attribute [Integer | Nil] The index where trailers begin. + attr :tail + # @returns [Array] The fields of the headers. def to_a @fields diff --git a/releases.md b/releases.md index 20ddb4f..31d0c19 100644 --- a/releases.md +++ b/releases.md @@ -3,6 +3,7 @@ ## Unreleased - Add `Protocol::HTTP::Headers#to_a` method that returns the fields array, providing compatibility with standard Ruby array conversion pattern. + - Expose `tail` in `Headers.new` so that trailers can be accurately reproduced. ## v0.51.0 diff --git a/test/protocol/http/headers.rb b/test/protocol/http/headers.rb index 3bb150f..9db3fd7 100644 --- a/test/protocol/http/headers.rb +++ b/test/protocol/http/headers.rb @@ -10,15 +10,25 @@ let(:fields) do [ ["Content-Type", "text/html"], + ["connection", "Keep-Alive"], ["Set-Cookie", "hello=world"], ["Accept", "*/*"], ["set-cookie", "foo=bar"], - ["connection", "Keep-Alive"] ] end let(:headers) {subject[fields]} + with ".new" do + it "can construct headers with trailers" do + headers = subject.new(fields, 4) + expect(headers).to be(:trailer?) + expect(headers.trailer.to_a).to be == [ + ["set-cookie", "foo=bar"], + ] + end + end + with ".[]" do it "can be constructed from frozen array" do self.fields.freeze @@ -29,13 +39,14 @@ with "#keys" do it "should return keys" do - expect(headers.keys).to be == ["content-type", "set-cookie", "accept", "connection"] + expect(headers.keys).to be == ["content-type", "connection", "set-cookie", "accept"] end end with "#trailer?" do it "should not be a trailer" do expect(headers).not.to be(:trailer?) + expect(headers.tail).to be_nil end end @@ -269,8 +280,10 @@ with "#trailer!" do it "can add trailer" do headers.add("trailer", "etag") + count = headers.fields.size trailer = headers.trailer! + expect(headers.tail).to be == count headers.add("etag", "abcd") @@ -345,8 +358,8 @@ describe Protocol::HTTP::Headers::Merged do let(:merged) do Protocol::HTTP::Headers::Merged.new( - Protocol::HTTP::Headers.new("content-type" => "text/html"), - Protocol::HTTP::Headers.new("content-encoding" => "gzip") + Protocol::HTTP::Headers["content-type" => "text/html"], + Protocol::HTTP::Headers["content-encoding" => "gzip"] ) end @@ -382,8 +395,8 @@ with "non-normalized case" do let(:merged) do Protocol::HTTP::Headers::Merged.new( - Protocol::HTTP::Headers.new("Content-Type" => "text/html"), - Protocol::HTTP::Headers.new("Content-Encoding" => "gzip") + Protocol::HTTP::Headers["Content-Type" => "text/html"], + Protocol::HTTP::Headers["Content-Encoding" => "gzip"] ) end