Repository navigation
Conversation
Multipart uploads parsed by Rack::Multipart create tempfiles that were left open on disk after the request unless the host app (e.g. Rails) already ran Rack::TempfileReaper. Use it in every endpoint's stack so they are closed and unlinked once the response body is closed. Fixes ruby-grape#2487
anyingiit
force-pushed
the
add-tempfile-reaper
branch
from
October 22, 2026 19:14
22f3f9f to
f2dbebb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by winshyon
Description
Multipart uploads parsed by
Rack::Multipartcreate tempfiles that are only cleaned up when something runsRack::TempfileReaper. Rails includes it by default, but a Grape API served directly by Rack (or by any non-Rails host) left those tempfiles on disk until GC/process exit, as described in #2487.This adds
Rack::TempfileReaperas the outermost middleware inGrape::Endpoint#build_stack(beforeRack::HeadandGrape::Middleware::Error), so the files are closed and unlinked once the response body is closed. Because it sits outside the error middleware, files are also reaped when the endpoint ends witherror!/a rescued exception, and the reaper itself closes them if an exception escapes.Notes for reviewers:
env['rack.tempfiles'] ||= []and both reapers justclose!the same tempfiles (Tempfile#close!on an already closed/unlinked file is a no-op). I checked this with an outerRack::TempfileReaperwrapping a Grape API on Rack 3.2.7 and Rack 2.2.24: 201 response, tempfile unlinked, no error.Rack::BodyProxyper request on the endpoint stack. I put it in the endpoint stack (rather than the API instance) to mirrorRack::Head, which already lives there; happy to move it if you prefer it elsewhere.spec/grape/integration/rack_spec.rb.Motivation / disclosure: I had some spare AI-assistant quota (Claude Code) and am using it to try to
help projects with open good-first-issues. The change was prepared with Claude Code and verified as listed
below. If it doesn't fit, isn't up to your bar, or you'd simply rather not take it — please feel free to
close it, no hard feelings at all 🙂
Related issue
Closes #2487
Checklist
bundle exec rake: RuboCop 358 files, no offenses; RSpec 3155 examples, 0 failures on currentmaster. Before rebasing, alsorspec spec --exclude-pattern=...withgemfiles/rack_2_2.gemfile(3079 examples, 0 failures) andgemfiles/rails_8_1.gemfile(3077 examples, 0 failures). The 2 new examples inspec/grape/integration/rack_spec.rbfail onmasterwithout the change on both Rack 3.2 and Rack 2.2)CHANGELOG.mdis updated (if applicable) — one line under 4.1.0 Features🤖 Generated with Claude Code