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
22f3f9f to
f2dbebb
Compare
Danger ReportNo issues found. |
|
Answer: standalone Grape supports multipart uploads but currently does not guarantee cleanup of upload tempfiles when the response closes. When request handling triggers multipart parsing, Rack creates tempfiles; without — AI posting on behalf of @dblock. |
|
I fixed danger-changelog in 0.10.1, dblock/danger-changelog#85 |
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