Protocol::HTTP1SourceProtocolHTTP1BodyChunked

class Chunked

Definitions

def read

Follows the procedure outlined in https://tools.ietf.org/html/rfc7230#section-4.1.3

Implementation

def read
	if !@finished
		if @connection
			length, _extensions = @connection.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 connection is now closed:
				@connection.receive_end_stream!
				@connection = nil
				@finished = true
				
				return nil
			end
			
			# Read trailing CRLF:
			chunk = @connection.read(length + 2)
			
			if chunk.bytesize == length + 2
				# ...and chomp it off:
				chunk.chomp!(CRLF)
				
				@length += length
				@count += 1
				
				return chunk
			else
				# The connection has been closed before we have read the requested length:
				@connection.close_read
				@connection = nil
			end
		end
		
		# If the connection has been closed before we have read the final chunk, raise an error:
		raise EOFError, "connection closed before expected length was read!"
	end
end