Skip to content

fix: keep the other media type parameters in MultiPartRepresentation.setBoundary - #1606

Merged
jlouvel merged 2 commits into
3.0from
fix/multipart-boundary-parameters
Nov 2, 2026
Merged

jlouvel merged 2 commits into
3.0from
fix/multipart-boundary-parameters

Conversation

@jlouvel

@jlouvel jlouvel commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

Fixes #1600.

Summary

When the media type already had a boundary, MultiPartRepresentation.setBoundary(MediaType, String) rebuilt it from the parent type with the boundary only. So multipart/mixed; boundary=a; deferSpec=20220824 became multipart/mixed; boundary=b. The instance method setBoundary(String) delegates to it and had the same effect.

setBoundary now edits the media type's name, which holds all its parameters:

  • it removes the existing boundary parameter, ignoring case and ; inside quoted values;
  • it keeps the other parameters as written;
  • it appends the new boundary through the existing constructor, which quotes it if needed.

The result is unchanged when there was no boundary yet. When a boundary is replaced, it now comes last, which doesn't change the meaning.

Why the name and not getParameters()

MediaType has two quirks that make getParameters() unreliable here:

  • Inherited parameters are missing. new MediaType(original, name, value) keeps the original's parameters in the name, but getParameters() returns only the new parameter.
  • Parsed parameters are not normalized. MediaType.valueOf("a/b; x=1; y=\"z\"") parses its parameters lazily with Form. Names after the first keep their leading space, and quoted values keep their quotes.

Neither quirk is changed here.

Testing

MultiPartRepresentationTestCase.setBoundaryKeepsTheOtherParameters covers:

  • a media type without a boundary;
  • replacing an existing boundary;
  • a quoted value containing ;boundary=;
  • an uppercase BOUNDARY from a parameter series, as parsed from a header;
  • a null media type;
  • the instance method.

It failed before the fix. The multipart, MediaType and Form tests pass locally (66 tests). The full core suite runs on CI.

🤖 Generated with Claude Code

@jlouvel jlouvel self-assigned this Oct 31, 2026
@jlouvel
jlouvel requested a balanced review from Copilot October 31, 2026 07:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The boundary update introduces a NullPointerException for supported null media-type names and discards original descriptions when adding a boundary.

2 open issues
What changed in this PR

This PR addresses #1600 by preserving other media type parameters when MultiPartRepresentation.setBoundary replaces an existing boundary.

Changes:

  • Removes existing boundary parameters case-insensitively while respecting quoted values, then appends the new boundary.
  • Adds regression coverage for parameter preservation, header-style parameters, null media types, and the instance setter.
  • Documents the fix in the changelog.
File Description
org.restlet/​src/​test/​java/​org/​restlet/​engine/​connector/​MultiPartRepresentationTestCase.java Adds boundary replacement regression tests.
org.restlet/​src/​main/​java/​org/​restlet/​representation/​MultiPartRepresentation.java Preserves other parameters during boundary replacement and updates documentation.
changes.md Records the fix for #1600.

Review effort: Balanced

@jlouvel
jlouvel force-pushed the fix/multipart-boundary-parameters branch from dde8c94 to 783fb09 Compare November 1, 2026 14:58
jlouvel and others added 2 commits November 1, 2026 21:11
…setBoundary

When the media type already had a boundary, setBoundary rebuilt it from
the parent type with the boundary only, so "multipart/mixed; boundary=a;
deferSpec=20220824" lost deferSpec.

A media type's name holds all its parameters, while getParameters() can
miss those inherited from an original type. setBoundary now removes the
boundary from the name, ignoring case and quoted ';', keeps the other
parameters as written, and appends the new boundary.

Fixes #1600.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Jerome Louvel <[email protected]>
…etBoundary

The media type rebuilt without its boundary parameters got the generic
description, so even MediaType.MULTIPART_FORM_DATA lost its own. It now
keeps the original description. A media type with a null name, which
MediaType accepts for backward compatibility, made setBoundary fail with a
NullPointerException; its name is now kept as is.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@jlouvel
jlouvel force-pushed the fix/multipart-boundary-parameters branch from b395614 to 1db2640 Compare November 2, 2026 02:11
@sonarqubecloud

sonarqubecloud Bot commented Nov 2, 2026

Copy link
Copy Markdown

@jlouvel
jlouvel merged commit 2ddea49 into 3.0 Nov 2, 2026
3 checks passed
@jlouvel
jlouvel deleted the fix/multipart-boundary-parameters branch November 2, 2026 02:23
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.

2 participants