9
9
module Protocol
10
10
module HTTP1
11
11
module Body
12
+ # Represents a chunked body, which is a series of chunks, each with a length prefix.
13
+ #
14
+ # See https://tools.ietf.org/html/rfc7230#section-4.1 for more details on the chunked transfer encoding.
12
15
class Chunked < HTTP ::Body ::Readable
13
16
CRLF = "\r \n "
14
17
18
+ # Initialize the chunked body.
19
+ #
20
+ # @parameter connection [Protocol::HTTP1::Connection] the connection to read the body from.
21
+ # @parameter headers [Protocol::HTTP::Headers] the headers to read the trailer into, if any.
15
22
def initialize ( connection , headers )
16
23
@connection = connection
17
24
@finished = false
@@ -22,19 +29,25 @@ def initialize(connection, headers)
22
29
@count = 0
23
30
end
24
31
32
+ # @attribute [Integer] the number of chunks read so far.
25
33
attr :count
26
34
35
+ # @attribute [Integer] the length of the body if known.
27
36
def length
28
- # We only know the length once we've read everything. This is because the length is not known until the final chunk is read.
37
+ # We only know the length once we've read the final chunk:
29
38
if @finished
30
39
@length
31
40
end
32
41
end
33
42
43
+ # @returns [Boolean] true if the body is empty, in other words {read} will return `nil`.
34
44
def empty?
35
45
@connection . nil?
36
46
end
37
47
48
+ # Close the connection and mark the body as finished.
49
+ #
50
+ # @parameter error [Exception | Nil] the error that caused the body to be closed, if any.
38
51
def close ( error = nil )
39
52
if connection = @connection
40
53
@connection = nil
@@ -49,7 +62,12 @@ def close(error = nil)
49
62
50
63
VALID_CHUNK_LENGTH = /\A [0-9a-fA-F]+\z /
51
64
65
+ # Read a chunk of data.
66
+ #
52
67
# Follows the procedure outlined in https://tools.ietf.org/html/rfc7230#section-4.1.3
68
+ #
69
+ # @returns [String | Nil] the next chunk of data, or `nil` if the body is finished.
70
+ # @raises [EOFError] if the connection is closed before the expected length is read.
53
71
def read
54
72
if !@finished
55
73
if @connection
@@ -96,12 +114,14 @@ def read
96
114
end
97
115
end
98
116
117
+ # @returns [String] a human-readable representation of the body.
99
118
def inspect
100
119
"\# <#{ self . class } #{ @length } bytes read in #{ @count } chunks>"
101
120
end
102
121
103
122
private
104
123
124
+ # Read the trailer from the connection, and add any headers to the trailer.
105
125
def read_trailer
106
126
while line = @connection . read_line?
107
127
# Empty line indicates end of trailer:
0 commit comments