-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
I have the following request mapping defined which includes 2 parts:
- metadata: POJO (application/json)
- files: multipart
@RequestMapping(
method = RequestMethod.POST,
value = "/v1/files/bulk",
produces = { "application/json" },
consumes = "multipart/form-data"
)
ResponseEntity<Files> saveFiles(
@Parameter(name = "metadata", description = "Array of file attributes", required = true) @Valid @RequestPart(value = "metadata", required = true) List<@Valid Metadata> metadata,
@Parameter(name = "files", description = "Array of Files") @RequestPart(value = "files", required = false) List<MultipartFile> files
);
which produces the following body:
--195903cbf58
Content-Disposition: form-data; name="metadata"
Content-Type: text/plain; charset=UTF-8
[{"fileName":"somefileName","hash":"somehash"}]
--195903cbf58
Content-Disposition: form-data; name="files"; filename=""
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
--195903cbf58--
It shows that the content type of the JSON part is set to text/plain instead of application/json.
This is due to the fact that feign.form.multipart.DelegateWriter#parameterWriter created in feign.form.MultipartFormContentProcessor#MultipartFormContentProcessor is set to feign.form.multipart.SingleParameterWriter which is using a hard-coded content-type of text/plain.
I have noticed that the RequestTemplate that is used to write the JSON data actually has the correct headers set ("Content-Type: application/json"). However, this is ignored as the hard-coded value is used.
I would expect that the content type is taken from the RequestTemplate.
The only workaround that I found is to do a String replace on the body like this:
public class SpringFormEncoderWithContentTypeCorrection extends SpringFormEncoder {
private static final String CONTENT_TYPE_STRING_TO_REPLACE = "Content-Type: text/plain; charset=";
private static final String NEW_CONTENT_TYPE_STRING = "Content-Type: application/json; charset=";
public SpringFormEncoderWithContentTypeCorrection(Encoder delegate) {
super(delegate);
}
@Override
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
super.encode(object, bodyType, template);
if (template.body() != null) {
// modify content type from 'text/plain' to 'application/json' for json parts
String modifiedContent = (new String(template.body())).replace(CONTENT_TYPE_STRING_TO_REPLACE, NEW_CONTENT_TYPE_STRING);
template.body(modifiedContent);
}
}
}
Configuration:
@Bean
@Primary
@Scope("prototype")
public Encoder feignFormEncoder(final ObjectFactory<HttpMessageConverters> messageConverters) {
return new SpringFormEncoderWithContentTypeCorrection(new SpringEncoder(messageConverters));
}
Versions used:
- openfeign: 13.5
- spring-cloud-openfeign-core: 4.2.0
- Spring Boot: 3.4.2