[backport camel-spring-boot-4.22.x] CAMEL-24593: platform-http-starter - delete multipart uploads when the exchange is done - #1966
Merged
Croway merged 1 commit intoSep 9, 2026
Conversation
…e exchange is done
SpringBootPlatformHttpBinding.populateAttachments() copies every accepted
multipart upload into the servlet temp directory and uses that copy as the
attachment DataSource and, for a single upload, as the Path message body and
the CamelFilePath header. MultipartFile.transferTo() moves the container's part
file, so the container's own end-of-request cleanup no longer finds it, and
nothing in the starter deleted the copy either: every upload the application
accepted stayed on disk for the life of the process.
The copy was introduced in CAMEL-21461 so the body can be a Path and the
attachment stays readable after the servlet request completed, which is a good
reason to own the file - but owning it means removing it. The other HTTP
bindings do not leak: camel-http-common reads the part through the container
managed file, which the container deletes, and camel-platform-http-vertx has
deleteUploadedFilesOnEnd defaulting to true.
The binding now collects the temp files it created for a request and registers
a Synchronization through ExchangeExtension.addOnCompletion that deletes them
when the exchange is done being routed. The DataSource and the Path body point
at the files until then, so they cannot be deleted any earlier; the consumer
writes the HTTP response before doneUoW, so the response is already out.
The opt-out mirrors the Vert.x option. Endpoint options are defined in upstream
camel-platform-http and cannot be extended from here, so the option is a new
starter owned configuration class, SpringBootPlatformHttpServerProperties,
next to the existing camel.component.platform-http.server.undertow.accesslog
properties:
camel.component.platform-http.server.delete-uploaded-files-on-end=false
It is wired from the auto configuration through the engine and the consumer
onto the binding, and defaults to true. Existing public constructors are
unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit cf374a9)
Croway
force-pushed
the
backport/1934-to-camel-spring-boot-4.22.x
branch
from
September 9, 2026 15:07
adfa2b7 to
08d3dd9
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.
Cherry-pick of #1934 onto
camel-spring-boot-4.22.x.Original PR: #1934 — platform-http-starter - delete multipart uploads when the exchange is done
JIRA: CAMEL-24593
What it fixes
SpringBootPlatformHttpBinding.populateAttachments()copies every accepted multipart upload out ofthe servlet container into the servlet temp directory, and uses that copy as the attachment
DataSourceand, for a single upload, as thePathmessage body and theCamelFilePathheader.Because
MultipartFile.transferTo()moves the container's part file, the container's ownend-of-request cleanup can no longer find it, and nothing in the starter deleted the copy either —
every accepted upload stayed on disk for the life of the process.
The copy was introduced in CAMEL-21461 so the body can be a
Pathand the attachment stays readableafter the servlet request has completed, which is a good reason to own the file — but owning it means
being responsible for removing it too. The other HTTP bindings don't have this problem:
camel-http-commonreads the part through the container-managed file (which the container deletes),and
camel-platform-http-vertxalready defaultsdeleteUploadedFilesOnEndtotrue.The binding now tracks the temp files it created for a request and registers a
Synchronizationvia
ExchangeExtension.addOnCompletionthat deletes them once the exchange is done being routed —after the HTTP response has already been written, so nothing currently reading the files is
affected. A new opt-out property,
camel.component.platform-http.server.delete-uploaded-files-on-end(default
true), mirrors the Vert.x option, for routes that hand the file to something that reads itafter the exchange completes.
This is a resource-leak fix only: no default-behavior change to existing routes, and existing public
constructors are unchanged.
Depends on CAMEL-24496, rebased onto CAMEL-24577
This cherry-picks onto
camel-spring-boot-4.22.xon top of CAMEL-24496 (#1953). Since this branchtracks
mainmuch more closely than 4.18.x, the original cherry-pick applied almost cleanly:SpringBootPlatformHttpAutoConfiguration.java,SpringBootPlatformHttpEngine.java,SpringBootPlatformHttpConsumer.java,SpringBootPlatformHttpBinding.javaand the aggregateddocs/spring-boot/modules/ROOT/pages/starters/platform-http.adocpage all auto-merged with nomanual intervention, and coexist correctly with CAMEL-24496's filename-whitelist checks (which run
earlier in
populateAttachments(), before this fix's cleanup registration).At the time this PR was opened, the only conflict was in the module-owned
components-starter/camel-platform-http-starter/src/main/docs/platform-http.adoc:main's diffcontext included a "Path variables" section from CAMEL-24577 (percent-decoded path placeholders),
which was not yet merged into this branch (still open as #1959 at the time). That section was left
out so as not to pull in unmerged content from a different ticket.
CAMEL-24577 (#1959) has since been merged into
camel-spring-boot-4.22.x, which made this PRconflict with the new base (same doc section reappearing, needing both kept). This branch has been
rebased onto the current tip: the "Path variables" section is restored alongside this PR's "File
uploads" section in
platform-http.adoc, andSpringBootPlatformHttpBinding.javanow carries bothfixes side by side — CAMEL-24577's path-variable read (
ServletRequestPathUtils.parse(request)) andthis PR's upload-cleanup tracking/registration are in different parts of the class and did not
actually overlap on any line.
Verification on this branch
described above; resolved by keeping both the "Path variables" and "File uploads" sections. The
Java file merged cleanly (no conflict markers), and its diff against the new base shows only this
PR's own changes.
./mvnw -DskipTests -Dfastinstall install -pl components-starter/camel-platform-http-starter -am(parent/
camel-versionand the ~535 hardcodedorg.apache.camel/org.apache.camel.mavenSNAPSHOT entries in
tooling/camel-spring-boot-dependencies/pom.xmltemporarily repointed to thereleased
4.22.0for local resolution, reverted afterwards) — succeeded.../../mvnw verifyincomponents-starter/camel-platform-http-starter: 134 tests total (0failures, 0 errors, 2 pre-existing skips), including both CAMEL-24577's path-variable tests
(
SpringBootPlatformHttpPathVariableTest,SpringBootPlatformHttpBindingPathVariableTest) andCAMEL-24593's upload-cleanup tests (
SpringBootPlatformHttpUploadCleanupTest,SpringBootPlatformHttpUploadCleanupDisabledTest) passing.git diff origin/camel-spring-boot-4.22.x --statonly shows the 11 files touched bythis PR's own commit (temporary pom.xml/BOM/catalog build artifacts reverted before pushing).
Claude Code on behalf of Federico Mariani