Description
Describe the bug
Response body modification filter can interfere with other filters that are potentially modifying response body and as the result fail the request. (full reproducer and error details below).
For example we have a ModifyResponseBody
filter that accepts Map
and returns Map
. Also prior to that we set up a caching filter that can potentially prevent request from going further and just return existing(cached) value for that request. In that case ModifyResponseBody filter shouldn't be called at all since the response is being written prior to that in a different filter. However response is being written via response.writeWith
call, which is being overriden by response body modification filter and that call will fail with exception below.
Sample
Reproducer here: https://github.com/korektur/spring-cloud-gateway/blob/filter_modify_body/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterTests.java
Route:
.route("modify_response_java_test_with_filter",
r -> r.path("/withFilterAndModifier")
.filters(f -> f.setPath("/httpbin/")
.filter(cacheGatewayFilter)
.modifyResponseBody(Map.class, Map.class,
(webExchange, originalResponse) -> {
Map<String, Object> modifiedResponse = new HashMap<>();
modifiedResponse.put("value",
originalResponse);
modifiedResponse.put("length",
originalResponse
.size());
return Mono
.just(modifiedResponse);
}))
.uri(uri))
.build();
Intercepting filter:
return (exchange, chain) -> {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.OK);
DataBufferFactory dataBufferFactory = response.bufferFactory();
DataBuffer wrap = dataBufferFactory.wrap(
"{\"value\": \"intercepted\"}".getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(wrap))
.doOnSuccess(v -> response.setComplete());
};
Error:
org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/octet-stream' not supported for bodyType=java.util.Map<?, ?>
at org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders$12(BodyExtractors.java:201) ~[spring-webflux-5.2.6.BUILD-20200420.134351-81.jar:5.2.6.BUILD-SNAPSHOT]
Error goes away if first parameter of .modifyResponseBody
is set to String.class
, however in that case body is modifyed twice, once in caching layer and then in modifyResponseBody filter.