Parts coming as null, where as same working when uploading from postman, but it failing from angular/chrome agent and verified the request b/w postman and chrome both are similar
Code:
public Mono<ServerResponse> uploadDocument(ServerRequest request) {
return request
.body(BodyExtractors.toMultipartData())
.map(
parts -> {
log.info("parts size " + parts.size());
Map<String, Part> formParts = parts.toSingleValueMap();
log.error("Form data parts " + formParts.toString());
FormFieldPart uploadFormField = (FormFieldPart) formParts.get("fileUploadModel");
log.error("Form field value " + uploadFormField.toString());
FilePart file = (FilePart) formParts.get("file");
FileUploadModel fileUpload = fileUploadModelVO(uploadFormField);
return uploadDocumentService.uploadFile(fileUpload, file).map(this::documentMapper);
})
.flatMap(
document ->
ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(document, FileUploadModel.class));
}
Parts coming as null, where as same working when uploading from postman, but it failing from angular/chrome agent and verified the request b/w postman and chrome both are similar
public Mono<ServerResponse> uploadDocument(ServerRequest request) {
return request
.body(BodyExtractors.toMultipartData())
.map(
parts -> {
log.info("parts size " + parts.size());
Map<String, Part> formParts = parts.toSingleValueMap();
log.error("Form data parts " + formParts.toString());
FormFieldPart uploadFormField = (FormFieldPart) formParts.get("fileUploadModel");
log.error("Form field value " + uploadFormField.toString());
FilePart file = (FilePart) formParts.get("file");
FileUploadModel fileUpload = fileUploadModelVO(uploadFormField);
return uploadDocumentService.uploadFile(fileUpload, file).map(this::documentMapper);
})
.flatMap(
document ->
ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(document, FileUploadModel.class));
}
Postman Request:
Warning: Self signed certificate in certificate chain
POST /eap/consultation/document/uploadDocument/ HTTP/1.1
User-Agent: PostmanRuntime/7.28.4
Accept: */*
Postman-Token: f98a5224-a2f3-4609-b2e5-219a03cc6b82
Host: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: multipart/form-data; boundary=------------------------- -019436366390284846853277
Content-Length: 178369
----------------------------019436366390284846853277
Content-Disposition: form-data; name="file"; filename="Gmail - Your Zomato order from Pista House (1).PDF"
<Gmail - Your Zomato order from Pista House (1).PDF>
----------------------------019436366390284846853277
Content-Disposition: form-data; name="fileUploadModel" { "fileName":"fileee2ff333", "description": "url changes", "caseId":"50" }
----------------------------019436366390284846853277--
Chrome Request:
POST /eap/consultation/document/uploadDocument HTTP/1.1
Host: xxxxxxxxxxxxxxxxxxxxxx
Connection: keep-alive
Content-Length: 178351
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
Accept: */*
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarySwprz3OeLnKlYLf8
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 sec-ch-ua-platform: "Windows"
Origin: https:/*********************
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://***************************
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
------WebKitFormBoundaryCXUDq20q3OAAg1eO
Content-Disposition: form-data; name="file"; filename="Food-bill.pdf"
Content-Type: application/pdf
------WebKitFormBoundaryCXUDq20q3OAAg1eO
Content-Disposition: form-data; name="fileUploadModel"
{"caseId":1011,"description":"","fileName":"Food-bill.pdf"}
------WebKitFormBoundaryCXUDq20q3OAAg1eO--
Service configuration:
@Configuration
@EnableWebFlux
public class ConsultationServWebConfig implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
SynchronossPartHttpMessageReader partReader = new SynchronossPartHttpMessageReader();
partReader.setEnableLoggingRequestDetails(true);
MultipartHttpMessageReader multipartReader = new MultipartHttpMessageReader(partReader);
multipartReader.setEnableLoggingRequestDetails(true);
configurer.defaultCodecs().multipartReader(multipartReader);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedHeaders("*").allowedMethods("*").allowedOrigins("*");
}
}
With SynchronossPartHttpMessageReader parts coming as null from angular where as same working from postman.
DefaultPartHttpMessageReader giving decoding exception could not find end of the body where as same working from postman
Comment From: poutsma
Which version of Spring Framework are you using? There have been several fixes to the DefaultPartHttpMessageReader
recently (i.e. #27939, #27612).
Comment From: bsreddy125
Which version of Spring Framework are you using? There have been several fixes to the
DefaultPartHttpMessageReader
recently (i.e. #27939, #27612).
2.6.2 and 2.5.5 versions, tried with both are causing same. Is any configuration required in filters?
Comment From: poutsma
2.6.2 and 2.5.5 versions, tried with both are causing same.
That's Spring Boot 2.6.2, so Spring Framework 5.3.14.
I think this issue might related to #27939, which was fixed in Spring Framework 5.3.16 and will be in Spring Boot 2.6.4, due out this Thursday.
If you want to try the fix now, you can upgrade to Spring Boot 2.6.3, and set the spring-framework.version
property to 5.3.16
in your pom.xml
or build.gradle
.
Comment From: bsreddy125
2.6.2 and 2.5.5 versions, tried with both are causing same.
That's Spring Boot 2.6.2, so Spring Framework 5.3.14.
I think this issue might related to #27939, which was fixed in Spring Framework 5.3.16 and will be in Spring Boot 2.6.4, due out this Thursday.
If you want to try the fix now, you can upgrade to Spring Boot 2.6.3, and set the
spring-framework.version
property to5.3.16
in yourpom.xml
orbuild.gradle
.
With the mentioned versions experiencing some other error "trace": "org.springframework.core.codec.DecodingException: Could not find first boundary\n\tat org.springframework.http.codec.multipart.MultipartParser$PreambleState.onComplete(MultipartParser.java:321)\
Is multipart upload dependent with server connection time out, initially i got 504 error then tried with10kb file then noticed decoding error
application.yml
config
```spring:
webflux:
basepath: eap/consultation
multipart:
max-in-memory-size: 10MB
data:
mongodb:
uri: ${MONGO_DB_URI:mongodb://localhost:27017/eap}
codec:
max-in-memory-size: 10MB
log-request-details: true
servlet:
multipart:
enabled: true
max-file-size: 10MB
max-request-size: 10MB
server: port: 9103 netty: initial-buffer-size: 10MB max-chunk-size: 10MB connection-timeout: 300000
logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions: TRACE
logging.level.reactor.netty.http.client.HttpClient: DEBUG
spring.mongodb.embedded.version: 5.0.5```
Comment From: poutsma
In an earlier comment (now deleted) I wrote that I could reproduce this, but I was wrong. Uploading multipart data from Chrome works fine for me.
From your comments I gather that both the DefaultPartHttpMessageReader
and the SynchronossPartHttpMessageReader
have problems with the data submitted by Angular, and that both work fine with data submitted from Postman. This suggest to me that Angular is sending malformed multipart data, but I cannot be sure unless I can reproduce the issue.
So if you'd like us to spend some time investigating, please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.
Comment From: bsreddy125
In an earlier comment (now deleted) I wrote that I could reproduce this, but I was wrong. Uploading multipart data from Chrome works fine for me.
From your comments I gather that both the
DefaultPartHttpMessageReader
and theSynchronossPartHttpMessageReader
have problems with the data submitted by Angular, and that both work fine with data submitted from Postman. This suggest to me that Angular is sending malformed multipart data, but I cannot be sure unless I can reproduce the issue.So if you'd like us to spend some time investigating, please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.
We are having this issue only in non prod environments. Its happening in when service deployed in docker containers in linux environments. In local its working. Is any decoding configuration or server level configuration required?
Comment From: poutsma
We are having this issue only in non prod environments. Its happening in when service deployed in docker containers in linux environments. In local its working. Is any decoding configuration or server level configuration required?
No additional configuration should be required, given that the size of the files you are sending are not that large (178,351 bytes, looking at the Content-Length
header).
It's interesting that the bug only occurs in production. That would suggest that the HTTP headers or body are manipulated somehow in this environment.
To give a better indication of what's goin on, you can try setting the org.springframework.http.codec.multipart
log level to TRACE
. That can give a lot of output, so I would suggest only doing that temporarily.
Comment From: bsreddy125
We are having this issue only in non prod environments. Its happening in when service deployed in docker containers in linux environments. In local its working. Is any decoding configuration or server level configuration required?
No additional configuration should be required, given that the size of the files you are sending are not that large (178,351 bytes, looking at the
Content-Length
header).It's interesting that the bug only occurs in production. That would suggest that the HTTP headers or body are manipulated somehow in this environment. To give a better indication of what's goin on, you can try setting the
org.springframework.http.codec.multipart
log level toTRACE
. That can give a lot of output, so I would suggest only doing that temporarily.
Postman request trace logs
:
2022-03-01 18:52:02.925 TRACE 1 --- [tor-thread-1255] o.s.h.codec.multipart.MultipartParser : First boundary found @51 in DefaultDataBuffer (r: 0, w: 158, c: 158) 2022-03-01 18:52:02.927 TRACE 1 --- [tor-thread-1255] o.s.h.codec.multipart.MultipartParser : Changed state: PREAMBLE -> HEADERS 2022-03-01 18:52:02.928 TRACE 1 --- [tor-thread-1255] o.s.h.codec.multipart.MultipartParser : End of headers found @105 in DefaultDataBuffer (r: 0, w: 106, c: 106) 2022-03-01 18:52:02.928 TRACE 1 --- [tor-thread-1255] o.s.h.codec.multipart.MultipartParser : Emitting headers: [Content-Disposition:"form-data; name="file"; filename="Food-bill.pdf"", Content-Type:"application/pdf"] 2022-03-01 18:52:02.929 TRACE 1 --- [tor-thread-1255] o.s.http.codec.multipart.PartGenerator : Changed state: INITIAL -> IN-MEMORY 2022-03-01 18:52:02.929 TRACE 1 --- [tor-thread-1255] o.s.h.codec.multipart.MultipartParser : Changed state: HEADERS -> BODY 2022-03-01 18:52:03.859 TRACE 1 --- [tor-thread-1262] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 5977, c: 5977) 2022-03-01 18:52:03.862 TRACE 1 --- [tor-thread-1262] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 18:52:03.864 TRACE 1 --- [tor-thread-1262] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 18:52:03.865 TRACE 1 --- [tor-thread-1262] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:12.714 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : First boundary found @51 in DefaultDataBuffer (r: 0, w: 153, c: 153) 2022-03-01 19:03:12.715 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Changed state: PREAMBLE -> HEADERS 2022-03-01 19:03:12.716 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : End of headers found @100 in DefaultDataBuffer (r: 0, w: 101, c: 101) 2022-03-01 19:03:12.717 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Emitting headers: [Content-Disposition:"form-data; name="file"; filename="June.pdf"", Content-Type:"application/pdf"] 2022-03-01 19:03:12.717 TRACE 1 --- [tor-thread-1365] o.s.http.codec.multipart.PartGenerator : Changed state: INITIAL -> IN-MEMORY 2022-03-01 19:03:12.717 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Changed state: HEADERS -> BODY 2022-03-01 19:03:13.303 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 5982, c: 5982) 2022-03-01 19:03:13.305 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.306 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.307 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.308 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.309 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.310 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.310 TRACE 1 --- [tor-thread-1365] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.617 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.620 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.621 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.623 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.624 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.626 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.627 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.629 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.630 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.632 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.633 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.635 TRACE 1 --- [tor-thread-1344] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.920 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.922 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.923 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.924 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.925 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.925 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Boundary found @1851 in DefaultDataBuffer (r: 0, w: 2080, c: 2080) 2022-03-01 19:03:13.926 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:03:13.926 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 1798, c: 1798) 2022-03-01 19:03:13.927 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Changed state: BODY -> HEADERS 2022-03-01 19:03:13.927 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : End of headers found @91 in DefaultDataBuffer (r: 0, w: 228, c: 228) 2022-03-01 19:03:13.928 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Emitting headers: [Content-Disposition:"form-data; name="fileUploadModel"", Content-Type:"application/json"] 2022-03-01 19:03:13.929 TRACE 1 --- [tor-thread-1372] o.s.http.codec.multipart.PartGenerator : Emitting: DefaultFilePart{file (June.pdf)} 2022-03-01 19:03:13.929 TRACE 1 --- [tor-thread-1372] o.s.http.codec.multipart.PartGenerator : Changed state: IN-MEMORY -> IN-MEMORY 2022-03-01 19:03:13.930 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Changed state: HEADERS -> BODY 2022-03-01 19:03:13.930 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Boundary found @131 in DefaultDataBuffer (r: 0, w: 136, c: 136) 2022-03-01 19:03:13.931 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 78, c: 78) 2022-03-01 19:03:13.931 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Changed state: BODY -> HEADERS 2022-03-01 19:03:13.931 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Last boundary found in DefaultDataBuffer (r: 0, w: 4, c: 4) 2022-03-01 19:03:13.932 TRACE 1 --- [tor-thread-1372] o.s.h.codec.multipart.MultipartParser : Changed state: HEADERS -> DISPOSED 2022-03-01 19:03:13.932 TRACE 1 --- [tor-thread-1372] o.s.http.codec.multipart.PartGenerator : Emitting: DefaultPart{fileUploadModel} 2022-03-01 19:03:13.933 TRACE 1 --- [tor-thread-1372] o.s.h.c.m.MultipartHttpMessageReader : [f01d3c1] Parsed {file=[DefaultFilePart{file (June.pdf)}], fileUploadModel=[DefaultPart{fileUploadModel}]}
===============================
Web Request trace logs
:
2022-03-01 19:08:44.787 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : First boundary found @38 in DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:44.788 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : Changed state: PREAMBLE -> HEADERS 2022-03-01 19:08:44.788 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : End of headers found @100 in DefaultDataBuffer (r: 0, w: 8153, c: 8153) 2022-03-01 19:08:44.789 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : Emitting headers: [Content-Disposition:"form-data; name="file"; filename="June.pdf"", Content-Type:"application/pdf"] 2022-03-01 19:08:44.790 TRACE 1 --- [tor-thread-1431] o.s.http.codec.multipart.PartGenerator : Changed state: INITIAL -> IN-MEMORY 2022-03-01 19:08:44.790 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : Changed state: HEADERS -> BODY 2022-03-01 19:08:44.791 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8052, c: 8052) 2022-03-01 19:08:44.792 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:44.793 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.093 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.095 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.095 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.096 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.398 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.399 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.400 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.401 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.403 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.404 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.405 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.405 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.407 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.407 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.408 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.409 TRACE 1 --- [tor-thread-1417] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.473 TRACE 1 --- [tor-thread-1429] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.474 TRACE 1 --- [tor-thread-1429] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.475 TRACE 1 --- [tor-thread-1429] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.476 TRACE 1 --- [tor-thread-1429] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.710 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.711 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : Emitting body: DefaultDataBuffer (r: 0, w: 8192, c: 8192) 2022-03-01 19:08:45.712 TRACE 1 --- [tor-thread-1431] o.s.h.codec.multipart.MultipartParser : Changed state: BODY -> DISPOSED 2022-03-01 19:08:45.712 TRACE 1 --- [tor-thread-1431] o.s.http.codec.multipart.PartGenerator : Changed state: IN-MEMORY -> DISPOSED 2022-03-01 19:08:45.716 ERROR 1 --- [tor-thread-1431] a.w.r.e.AbstractErrorWebExceptionHandler : [ed723985] 500 Server Error for HTTP POST "/upload/documentupload" org.springframework.core.codec.DecodingException: Could not find end of body at org.springframework.http.codec.multipart.MultipartParser$BodyState.onComplete(MultipartParser.java:553) ~[spring-web-5.3.14.jar:5.3.14]
Comment From: yelouarti
@bsreddy125 I faced a similar issue, where locally (Windows) it worked fine, but the same code remotely on a linux machine throwed an "org.springframework.core.codec.DecodingException: Could not find end of body". Given however, this behavior was observed during an integration test and not in production (i.e. with synthetic data).
The Setup
A total of 3 application are involved:
- Wiremock docker container that provides a response in multipart-data format
- Unit test that sets up the wiremock instance by feeding it the response multipart data and that calls the service-under-test (SuT).
- Service (i.e. the SuT) that consumes multipart data (from the wiremock) and which ultimately throws the
DecodingException
An important detail is that locally I'm working on Windows and Docker Desktop (enables docker under Windows).
(Disclaimer: This was my setup, you can achieve the error without a wiremock!)
Reason for the Error
The multipart data that the unit test used was created under Windows, which per default uses CRLF for line breaks. This is also how line breaks have to be implemented in multipart data according to RFC. This is also what the DefaultPartHttpMessageReader
expects.
Unfortunately I didn't realize, that Git was set up to automatically change in CRLF to linux style LF (here is a SO answer that explains this very nicely). In short, the test data with which the mock was fed was different locally and remotely on linux:
- locally: Unit test reads file with CRLF -> feeds wiremock -> SuT gets the unmodified file with CRLF -> ✔
- remotely: Pushed data was modified by Git -> unit test feeds "corrupt data" to mock -> SuT is looking for CRLF but can't find it -> ❌
How to Bypass the Error
- You could either change the settings of your version control
- Encode your data with CRLF e.g. in Base64 and push it to your repository. Now it can be decoded by your SuT or unit tests regardless of the OS and it will always contain the desired line breaks as the line breaks weren't modified because they were encoded.
You could fix this in more than the suggested ways honestly. It could as well be, that you have a similar, but not necessarily identical, issue @bsreddy125.
Suggestion for Spring
Regardless of whether OP has the same issue, I think it would be at least appreciated, if the exception details could hint a possible issue regarding line breaks. If not a single CRLF was found, chances are the data is corrupt, especially if LFs are available. I spent days looking for the error. However, I don't think this is an issue on Springs end to be honest.
Comment From: mukeshj13
Facing the same issue on MacOS local for a pdf file. Not sending the Content-Type header through postman, it is automatically adding that. DecodeException: Could not find first boundary at org.springframework.http.codec.multipart.MultipartParser$PreambleState.onComplete(MultipartParser.java:306) at org.springframework.http.codec.multipart.MultipartParser.hookOnComplete(MultipartParser.java:109) at reactor.core.publisher.BaseSubscriber.onComplete(BaseSubscriber.java:197) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) at reactor.core.publisher.Operators.complete(Operators.java:136)......
Comment From: poutsma
Resolved by changing the exception message so that it shows the exact string that the multipart parser is looking for (i.e. ␍␊--<boundary>
).