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