Skip to content

Commit 3b8b0d2

Browse files
tavianatorioquatix
authored andcommitted
Fix MockResponse#body when the body is a Proc (#2420)
- Ensure streaming response body is closed by `Rack::MockResponse`. (#2423)
1 parent 4c24539 commit 3b8b0d2

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to this project will be documented in this file. For info on how to format all future additions to this file please reference [Keep A Changelog](https://keepachangelog.com/en/1.0.0/).
44

5+
## Unreleased
6+
7+
### Fixed
8+
9+
- Fix `Rack::MockResponse#body` when the body is a Proc. ([#2420](https://github.com/rack/rack/pull/2420), [#2423](https://github.com/rack/rack/pull/2423), [@tavianator](https://github.com/tavianator), [@ioquatix])
10+
511
## [3.2.4] - 2025-11-03
612

713
### Fixed

lib/rack/mock_response.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# frozen_string_literal: true
22

3+
require 'stringio'
34
require 'time'
45

56
require_relative 'response'
@@ -82,8 +83,16 @@ def body
8283
# end
8384
buffer = @buffered_body = String.new
8485

85-
@body.each do |chunk|
86-
buffer << chunk
86+
begin
87+
if @body.respond_to?(:each)
88+
@body.each do |chunk|
89+
buffer << chunk
90+
end
91+
else
92+
@body.call(StringIO.new(buffer))
93+
end
94+
ensure
95+
@body.close if @body.respond_to?(:close)
8796
end
8897

8998
return buffer

test/spec_mock_response.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,42 @@ def close
230230
headers = res[1]
231231
refute headers.key?("content-length")
232232
end
233+
234+
it "handles Proc bodies" do
235+
headers = { "content-type" => "text/event-stream" }
236+
237+
body = proc do |stream|
238+
stream.write("Hello, ")
239+
stream.write("world!")
240+
end
241+
242+
response = Rack::MockResponse[200, headers, body]
243+
244+
response.status.must_equal 200
245+
response.headers.must_equal headers
246+
response.body.must_equal "Hello, world!"
247+
end
248+
249+
it "closes streaming bodies that respond to close" do
250+
closed = false
251+
252+
body = proc do |stream|
253+
stream.write("content")
254+
end
255+
256+
# Add a close method to the proc
257+
def body.close
258+
@closed = true
259+
end
260+
261+
def body.closed?
262+
@closed
263+
end
264+
265+
response = Rack::MockResponse[200, {}, body]
266+
response.body.must_equal "content"
267+
body.must_be :closed?
268+
end
233269
end
234270

235271
describe Rack::MockResponse, 'headers' do

0 commit comments

Comments
 (0)