lib/protocol/http1/body/chunked.rb in protocol-http1-0.10.3 vs lib/protocol/http1/body/chunked.rb in protocol-http1-0.11.0

- old
+ new

@@ -24,15 +24,19 @@ module Protocol module HTTP1 module Body class Chunked < HTTP::Body::Readable - # TODO maybe this should take a stream rather than a connection? - def initialize(stream) + TRAILERS = 'trailers' + CRLF = "\r\n" + + def initialize(stream, headers) @stream = stream @finished = false + @headers = headers + @length = 0 @count = 0 end def empty? @@ -47,25 +51,30 @@ end super end + # Follows the procedure outlined in https://tools.ietf.org/html/rfc7230#section-4.1.3 def read return nil if @finished length = read_line.to_i(16) if length == 0 @finished = true - read_line + read_trailers + return nil end - chunk = @stream.read(length) - read_line # Consume the trailing CRLF + # Read trailing CRLF: + chunk = @stream.read(length + 2) + # ...and chomp it off: + chunk.chomp!(CRLF) + @length += length @count += 1 return chunk end @@ -75,10 +84,25 @@ end private def read_line - @stream.gets(chomp: true) + @stream.gets(CRLF, chomp: true) + end + + def read_trailers + @headers.trailers! + + while line = read_line + # Empty line indicates end of headers: + break if line.empty? + + if match = line.match(HEADER) + @headers.add(match[1], match[2]) + else + raise BadHeader, "Could not parse header: #{line.dump}" + end + end end end end end end