lib/protocol/http1/body/chunked.rb in protocol-http1-0.21.0 vs lib/protocol/http1/body/chunked.rb in protocol-http1-0.22.0

- old
+ new

@@ -1,9 +1,9 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2019-2023, by Samuel Williams. +# Copyright, 2019-2024, by Samuel Williams. # Copyright, 2023, by Thomas Morgan. require 'protocol/http/body/readable' module Protocol @@ -21,55 +21,65 @@ @length = 0 @count = 0 end def empty? - @finished + @stream.nil? end def close(error = nil) - # We only close the connection if we haven't completed reading the entire body: - unless @finished - @stream.close - @finished = true + if @stream + # We only close the connection if we haven't completed reading the entire body: + unless @finished + @stream.close_read + end + + @stream = nil end super end VALID_CHUNK_LENGTH = /\A[0-9a-fA-F]+\z/ # Follows the procedure outlined in https://tools.ietf.org/html/rfc7230#section-4.1.3 def read - return nil if @finished - - length, _extensions = read_line.split(";", 2) - - unless length =~ VALID_CHUNK_LENGTH - raise BadRequest, "Invalid chunk length: #{length.inspect}" - end - - # It is possible this line contains chunk extension, so we use `to_i` to only consider the initial integral part: - length = Integer(length, 16) - - if length == 0 - @finished = true + if !@finished + if @stream + length, _extensions = read_line.split(";", 2) + + unless length =~ VALID_CHUNK_LENGTH + raise BadRequest, "Invalid chunk length: #{length.inspect}" + end + + # It is possible this line contains chunk extension, so we use `to_i` to only consider the initial integral part: + length = Integer(length, 16) + + if length == 0 + read_trailer + + # The final chunk has been read and the stream is now closed: + @stream = nil + @finished = true + + return nil + end + + # Read trailing CRLF: + chunk = @stream.read(length + 2) + + # ...and chomp it off: + chunk.chomp!(CRLF) + + @length += length + @count += 1 + + return chunk + end - read_trailer - - return nil + # If the stream has been closed before we have read the final chunk, raise an error: + raise EOFError, "Stream closed before expected length was read!" end - - # Read trailing CRLF: - chunk = @stream.read(length + 2) - - # ...and chomp it off: - chunk.chomp!(CRLF) - - @length += length - @count += 1 - - return chunk end def inspect "\#<#{self.class} #{@length} bytes read in #{@count} chunks>" end