@@ -32,11 +32,16 @@ class BodyReadWrapper < ::Protocol::HTTP::Body::Readable
32
32
#
33
33
# @parameter body [Interface(:read)] The input body to wrap.
34
34
# @parameter block_size [Integer] The size of the blocks to read from the body.
35
- def initialize ( body , block_size : 4096 )
35
+ # @parameter length [Integer | Nil] The length of the body, if known.
36
+ def initialize ( body , length = nil , block_size : 4096 )
36
37
@body = body
38
+ @length = length
37
39
@block_size = block_size
38
40
end
39
41
42
+ # @attribute [Integer | Nil] The total length of the body, or `nil` if the length is unknown.
43
+ attr :length
44
+
40
45
# Close the body if possible.
41
46
def close ( error = nil )
42
47
@body . close if @body . respond_to? ( :close )
@@ -168,28 +173,29 @@ def call(env)
168
173
169
174
def perform_request ( env )
170
175
with_client ( env ) do |endpoint , client |
176
+ if headers = env . request_headers
177
+ headers = ::Protocol ::HTTP ::Headers [ headers ]
178
+
179
+ # Use content-length to inform body length if given, but remove the header since it will be
180
+ # set for us later anyway, and not doing so could result in a duplicate content-length headers
181
+ # if capitalization differs
182
+ content_length = headers . delete ( "content-length" ) &.to_i
183
+ end
184
+
171
185
if body = env . body
172
186
# We need to ensure the body is wrapped in a Readable object so that it can be read in chunks:
173
187
# Faraday's body only responds to `#read`.
174
188
if body . is_a? ( ::Protocol ::HTTP ::Body ::Readable )
175
189
# Good to go
176
190
elsif body . respond_to? ( :read )
177
- body = BodyReadWrapper . new ( body )
191
+ body = BodyReadWrapper . new ( body , content_length )
178
192
else
179
- body = ::Protocol ::HTTP ::Body ::Buffered . wrap ( body )
193
+ body = ::Protocol ::HTTP ::Body ::Buffered . wrap ( body ) . then do |buffered |
194
+ ::Protocol ::HTTP ::Body ::Buffered . new ( buffered . chunks , content_length )
195
+ end
180
196
end
181
197
end
182
198
183
- if headers = env . request_headers
184
- # Ignore Content-Length if given, it will be set for us later anyway (lowercased)
185
- if headers . has_key? ( "Content-Length" )
186
- headers = headers . dup
187
- headers . delete ( "Content-Length" )
188
- end
189
-
190
- headers = ::Protocol ::HTTP ::Headers [ headers ]
191
- end
192
-
193
199
method = env . method . to_s . upcase
194
200
195
201
request = ::Protocol ::HTTP ::Request . new ( endpoint . scheme , endpoint . authority , method , endpoint . path , nil , headers , body )
0 commit comments