New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple writes to Rack::Response result in incorrect content-length header in Rack 3 #2148
Comments
Without digging into it, it appears that the latter |
I'm actually not sure I understand the intention of the existing code, in particular why The problem I see is that there is a missing assignment of Abbreviated, the code currently looks like this: if @buffered.nil?
if @body.is_a?(Array)
# ...
# ⚠️ @buffered is not set in this branch
elsif @body.respond_to?(:each)
# ...
@buffered = true
else
@buffered = false
end
end It seems like the point of this code was to lazily init --- lib/rack/response.rb
+++ lib/rack/response.rb
@@ -318,12 +318,14 @@ module Rack
if @body.is_a?(Array)
# The user supplied body was an array:
@body = @body.compact
@body.each do |part|
@length += part.to_s.bytesize
end
+
+ @buffered = true
elsif @body.respond_to?(:each)
# Turn the user supplied body into a buffered array:
body = @body
@body = Array.new
body.each do |part| With this one-line change, I get the correct content-length result when running my reproduction script. |
Do you mind making a PR? |
OK, I've opened PR #2150 |
Problem
After upgrading to Rack 3, I found that
Rack::Response
generates an incorrect content-length header when:write
is called multiple timesHere is a simple reproduction script:
Underlying cause
When
Rack::Response
is constructed with an empty array, it sets this internal state:rack/lib/rack/response.rb
Line 82 in 0cd4d40
This causes the value of
@length
to accumulate on every call toRack::Response#write
:rack/lib/rack/response.rb
Lines 317 to 323 in 0cd4d40
When
chunked?
isfalse
,@length
is incremented yet again, and then emitted as a content-length header:rack/lib/rack/response.rb
Lines 348 to 350 in 0cd4d40
The result is that the content-length value is too large, and the error gets larger on every call to
write
.The text was updated successfully, but these errors were encountered: