diff options
author | Jeremy Evans <code@jeremyevans.net> | 2023-03-24 17:01:03 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-24 17:01:03 -0700 |
commit | b172805895fc0490bf81e942487233e6771f4643 (patch) | |
tree | 893721c432e2dac98f2a0345bdfe9497a3b76aa7 | |
parent | d4c159f66a0bbf92be2512df2099698097d42120 (diff) | |
download | rack-b172805895fc0490bf81e942487233e6771f4643.tar.gz |
Handle string reuse by body.each when buffering bodies in Rack::Response (#2044)
An alternative approach would be using a single string inside an array
and appending to that. This approach is more backwards compatible,
but results in more memory usage.
Fixes #1957
-rw-r--r-- | lib/rack/response.rb | 1 | ||||
-rw-r--r-- | test/spec_response.rb | 20 |
2 files changed, 21 insertions, 0 deletions
diff --git a/lib/rack/response.rb b/lib/rack/response.rb index 4a6af373..20a87159 100644 --- a/lib/rack/response.rb +++ b/lib/rack/response.rb @@ -342,6 +342,7 @@ module Rack end def append(chunk) + chunk = chunk.dup unless chunk.frozen? @body << chunk unless chunked? diff --git a/test/spec_response.rb b/test/spec_response.rb index 68227fa6..6a6957e5 100644 --- a/test/spec_response.rb +++ b/test/spec_response.rb @@ -604,6 +604,26 @@ describe Rack::Response do res.finish.last.must_equal ["Foo", "Bar"] end + it "handles string reuse in existing body when calling #write" do + body_class = Class.new do + def initialize(file) + @file = file + end + + def each + buffer = String.new + + while @file.read(5, buffer) + yield(buffer) + end + end + end + body = body_class.new(StringIO.new('Large large file content')) + res = Rack::Response.new(body) + res.write(" written") + res.finish.last.must_equal ["Large", " larg", "e fil", "e con", "tent", " written"] + end + it "calls close on #body" do res = Rack::Response.new res.body = StringIO.new |