Affects: spring-webflux:5.2.10
If I try to send http-multipart request with precalculation content length - webclient will generated incorrect request.
For example
public Mono<String> sendMultipartWithLength() throws URISyntaxException {
var length = length();
return client.post()
.uri("http://localhost:8080/with/multipart")
.contentLength(length)
.contentType(MediaType.MULTIPART_FORM_DATA)
.bodyValue(files())
.retrieve()
.bodyToMono(String.class);
}
private MultiValueMap<String, HttpEntity<?>> files() throws URISyntaxException {
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("file1", new FileSystemResource(getFileFromResource("1.txt")));
builder.part("file2", new FileSystemResource(getFileFromResource("2.txt")));
builder.part("file3", new FileSystemResource(getFileFromResource("3.txt")));
return builder.build();
}
private long length() throws URISyntaxException {
long length = getFileFromResource("1.txt").length();
length += getFileFromResource("2.txt").length();
length += getFileFromResource("3.txt").length();
log.info("Content length {}", length);
return length;
}
See http-request: section "MIME Multipart Media Encapsulation, Type: multipart/form-data, ..." contains only 2 files and part of the file 3 (in section "Hypertext Transfer Protocol").
Is this a bug or is there a correct way to set the content-length?
Full example https://github.com/romus/client-multipart
Comment From: rstoyanchev
The length that you are computing upfront does not accurately reflect the entire length of the actual request body and I don't see a good way to compute it. In this case the computed content-length is shorter than the actual content and this is why the server cuts off the last part. So that's expected behavior.
A content-length at the top level needs to reflect the full request body. For a multipart request that means not just the content of each part but also the part headers as well as the multipart formatting and boundary delimiters. Note that when using Resource
with a known length, there is a content-length the headers for each part that reflects how large the content is.
Comment From: romus
Thank you!