Skip to content

fix(context): clean multipart temps after ServeHTTP - #4791

Open
RubenPari wants to merge 4 commits into
gin-gonic:masterfrom
RubenPari:fix/multipart-form-cleanup-withcontext
Open

RubenPari wants to merge 4 commits into
gin-gonic:masterfrom
RubenPari:fix/multipart-form-cleanup-withcontext

Conversation

@RubenPari

@RubenPari RubenPari commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Call unexported Context.cleanupMultipartForm() at the end of Engine.ServeHTTP so temp files from ParseMultipartForm are removed even when middleware replaces c.Request (e.g. OTEL WithContext).
  • net/http only runs MultipartForm.RemoveAll() on the original request handed to ServeHTTP; a shallow-copied request leaves /tmp/multipart-* orphaned (Why no call to Request.MultipartForm.RemoveAll #4278).
  • Double RemoveAll is safe when the request was not replaced (os.ErrNotExist ignored). No public API change. Supersedes the approach in clean up the multipart request files- this resolves #4278 #4279 (cleanup must live in Gin's request lifecycle, not binding).

Test plan

  • go test ./... -count=1 -run 'TestServeHTTPCleansMultipartForm|TestContextCleanupMultipartFormNilSafe'
  • go test . -count=1
  • Regression: middleware replaces request via WithContext, FormFile with body > MaxMultipartMemory → temp path gone after ServeHTTP
  • Same without middleware replace (double-cleanup path)
  • cleanupMultipartForm nil-safe for nil Request / nil MultipartForm

Fixes #4278

net/http only RemoveAlls the original Request. Middleware that
replaces c.Request via WithContext leaves /tmp/multipart-* from
FormFile/MultipartForm orphaned. Clean c.Request at ServeHTTP end.

Fixes gin-gonic#4278
staticcheck SA1029 forbids empty anonymous struct as context.WithValue
keys; use a local named type instead.
@codecov

codecov Bot commented Aug 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.65%. Comparing base (3b08cd7) to head (ed90302).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4791   +/-   ##
=======================================
  Coverage   98.65%   98.65%           
=======================================
  Files          48       48           
  Lines        3190     3194    +4     
=======================================
+ Hits         3147     3151    +4     
  Misses         43       43           
Flag Coverage Δ
--ldflags="-checklinkname=0" -tags sonic 98.64% <100.00%> (+<0.01%) ⬆️
-tags go_json 98.58% <100.00%> (+<0.01%) ⬆️
-tags nomsgpack 98.63% <100.00%> (+<0.01%) ⬆️
go-1.26 98.34% <100.00%> (+<0.01%) ⬆️
go-1.27 98.67% <100.00%> (+<0.01%) ⬆️
macos-latest 98.65% <100.00%> (+<0.01%) ⬆️
ubuntu-latest 98.65% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Why no call to Request.MultipartForm.RemoveAll

1 participant