Follow up changes in Servlet multipart support

Apply similar changes to the Servlet multipart message converter.

See gh-37264
This commit is contained in:
Brian Clozel
2026-09-10 14:41:13 +02:00
parent d1402d3c7f
commit b40ed77e94
2 changed files with 14 additions and 1 deletions
@@ -488,6 +488,7 @@ final class MultipartParser {
// iterate over buffers in reverse order // iterate over buffers in reverse order
DataBufferUtils.release(boundaryBuffer); DataBufferUtils.release(boundaryBuffer);
DataBuffer prev; DataBuffer prev;
boolean found = false;
while ((prev = this.queue.pollLast()) != null) { while ((prev = this.queue.pollLast()) != null) {
int prevByteCount = prev.readableByteCount(); int prevByteCount = prev.readableByteCount();
int prevLen = prevByteCount + len; int prevLen = prevByteCount + len;
@@ -497,6 +498,7 @@ final class MultipartParser {
DataBufferUtils.release(prev); DataBufferUtils.release(prev);
enqueue(body); enqueue(body);
flush(); flush();
found = true;
break; break;
} }
else { else {
@@ -505,12 +507,22 @@ final class MultipartParser {
len += prevByteCount; len += prevByteCount;
} }
} }
if (!found) {
// all buffered bytes were boundary bytes: the part had an empty body
invokeListener(buffer.factory().allocateBuffer(0), true);
}
} }
else /* if (len == 0) */ { else /* if (len == 0) */ {
// buffer starts with complete delimiter, flush out the previous buffers // buffer starts with complete delimiter, flush out the previous buffers
DataBufferUtils.release(boundaryBuffer); DataBufferUtils.release(boundaryBuffer);
if (this.queue.isEmpty()) {
// nothing was ever buffered for this part: the part had an empty body
invokeListener(buffer.factory().allocateBuffer(0), true);
}
else {
flush(); flush();
} }
}
changeState(new HeadersState(), buffer); changeState(new HeadersState(), buffer);
} }
@@ -118,6 +118,7 @@ class MultipartParserTests {
parse("no-body.multipart", "boundary", listener); parse("no-body.multipart", "boundary", listener);
listener.assertHeader(headers -> assertThat(headers.hasHeaderValues("Part", List.of("1"))).isTrue()) listener.assertHeader(headers -> assertThat(headers.hasHeaderValues("Part", List.of("1"))).isTrue())
.assertBodyChunk("")
.assertHeader(headers -> assertThat(headers.hasHeaderValues("Part", List.of("2"))).isTrue()) .assertHeader(headers -> assertThat(headers.hasHeaderValues("Part", List.of("2"))).isTrue())
.assertBodyChunk("a") .assertBodyChunk("a")
.assertComplete(); .assertComplete();