So Im using spring gateway to build a proxy like service and one job is to process the response and update it, so accordingly I wrote a gateway filter but it seems like it's not working as I expected.
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@Slf4j
@Component
public class ResponseTransformationGatewayFilterFactory extends AbstractGatewayFilterFactory<ResponseTransformationGatewayFilterFactory.Config> {
public ResponseTransformationGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
ModifyResponseBodyGatewayFilterFactory.Config modifyConfig = new ModifyResponseBodyGatewayFilterFactory.Config();
// used string.class but same issue
modifyConfig.setRewriteFunction(JsonNode.class, JsonNode.class, (exchange, originalResponseBody) -> {
// Transform the response body
JsonNode transformedBody = transformResponseBody(originalResponseBody);
return Mono.just(transformedBody);
});
return new ModifyResponseBodyGatewayFilterFactory(new ArrayList<>(), new HashSet<>(), new HashSet<>()).apply(modifyConfig);
}
private JsonNode transformResponseBody(JsonNode originalBody) {
// we can get rid of fields here.
return JsonResponseFilter.filter(originalBody, List.of("options"));
// only add options with included providers
}
public static class Config {
}
}
Error:
org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json' not supported for bodyType=com.fasterxml.jackson.databind.JsonNode
at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:205) ~[spring-webflux-6.0.12.jar:6.0.12]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ⇢ Body from UNKNOWN [DefaultClientResponse]
So the issue was in my web client configuration, I need to add Jackson Decoder
final ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs()
.jackson2JsonDecoder(new Jackson2JsonDecoder(mapper))
)
.build();
final var httpClient = HttpClient.create(provider)
.resolver(nameResolverSpec -> nameResolverSpec.cacheMaxTimeToLive(Duration.ofSeconds(60)))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT)
.doOnConnected(connection -> {
connection.addHandlerLast(new ReadTimeoutHandler(TIMEOUT, TimeUnit.SECONDS));
connection.addHandlerLast(new WriteTimeoutHandler(TIMEOUT, TimeUnit.SECONDS));
});
return WebClient.builder()
.baseUrl(baseUrl)
.exchangeStrategies(exchangeStrategies)
.defaultHeader(ACCEPT_HEADER, MediaType.ALL_VALUE)
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();