@@ -32,11 +32,16 @@ class BodyReadWrapper < ::Protocol::HTTP::Body::Readable
3232 #
3333 # @parameter body [Interface(:read)] The input body to wrap.
3434 # @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 )
3637 @body = body
38+ @length = length
3739 @block_size = block_size
3840 end
3941
42+ # @attribute [Integer | Nil] The total length of the body, or `nil` if the length is unknown.
43+ attr :length
44+
4045 # Close the body if possible.
4146 def close ( error = nil )
4247 @body . close if @body . respond_to? ( :close )
@@ -168,28 +173,29 @@ def call(env)
168173
169174 def perform_request ( env )
170175 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+
171185 if body = env . body
172186 # We need to ensure the body is wrapped in a Readable object so that it can be read in chunks:
173187 # Faraday's body only responds to `#read`.
174188 if body . is_a? ( ::Protocol ::HTTP ::Body ::Readable )
175189 # Good to go
176190 elsif body . respond_to? ( :read )
177- body = BodyReadWrapper . new ( body )
191+ body = BodyReadWrapper . new ( body , content_length )
178192 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
180196 end
181197 end
182198
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-
193199 method = env . method . to_s . upcase
194200
195201 request = ::Protocol ::HTTP ::Request . new ( endpoint . scheme , endpoint . authority , method , endpoint . path , nil , headers , body )
0 commit comments