具有 text/html 响应的 Reactive WebClient GET 请求
Reactive WebClient GET Request with text/html response
目前我在使用新的 Spring 5 WebClient 时遇到问题,我需要一些帮助来解决这个问题。
问题是:
I request some url that returns json response with content type text/html;charset=utf-8.
But unfortunately I’m still getting an exception:
org.springframework.web.reactive.function.UnsupportedMediaTypeException:
Content type 'text/html;charset=utf-8' not supported. So I can’t
convert response to DTO.
对于请求,我使用以下代码:
Flux<SomeDTO> response = WebClient.create("https://someUrl")
.get()
.uri("/someUri").accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToFlux(SomeDTO.class);
response.subscribe(System.out::println);
顺便说一句,我在 accept header 中指向哪个类型并不重要,总是返回 text/html。那么我怎样才能让我的回复最终得到转换呢?
让服务发送 JSON 和 "text/html"
Content-Type 是相当不寻常的。
有两种处理方法:
- 配置 Jackson 解码器以解码
"text/html"
内容;查看 WebClient.builder().exchangeStrategies(ExchangeStrategies)
设置方法
- 即时更改 "Content-Type" 响应 header
这是第二种解决方案的建议:
WebClient client = WebClient.builder().filter((request, next) -> next.exchange(request)
.map(response -> {
MyClientHttpResponseDecorator decorated = new
MyClientHttpResponseDecorator(response);
return decorated;
})).build();
class MyClientHttpResponseDecorator extends ClientHttpResponseDecorator {
private final HttpHeaders httpHeaders;
public MyClientHttpResponseDecorator(ClientHttpResponse delegate) {
super(delegate);
this.httpHeaders = new HttpHeaders(this.getDelegate().getHeaders());
// mutate the content-type header when necessary
}
@Override
public HttpHeaders getHeaders() {
return this.httpHeaders;
}
}
请注意,您应该只在该上下文中(针对该主机)使用该客户端。
如果可以的话,我强烈建议尝试修复服务器返回的奇怪 content-type。
如上一个回答所述,您可以使用 exchangeStrategies 方法,
示例:
Flux<SomeDTO> response = WebClient.builder()
.baseUrl(url)
.exchangeStrategies(ExchangeStrategies.builder().codecs(this::acceptedCodecs).build())
.build()
.get()
.uri(builder.toUriString(), 1L)
.retrieve()
.bodyToFlux( // .. business logic
private void acceptedCodecs(ClientCodecConfigurer clientCodecConfigurer) {
clientCodecConfigurer.customCodecs().encoder(new Jackson2JsonEncoder(new ObjectMapper(), TEXT_HTML));
clientCodecConfigurer.customCodecs().decoder(new Jackson2JsonDecoder(new ObjectMapper(), TEXT_HTML));
}
如果您需要设置 maxInMemorySize 以及 text/html 响应,请使用:
WebClient invoicesWebClient() {
return WebClient.builder()
.exchangeStrategies(ExchangeStrategies.builder().codecs(this::acceptedCodecs).build())
.build();
}
private void acceptedCodecs(ClientCodecConfigurer clientCodecConfigurer) {
clientCodecConfigurer.defaultCodecs().maxInMemorySize(BUFFER_SIZE_16MB);
clientCodecConfigurer.customCodecs().registerWithDefaultConfig(new Jackson2JsonDecoder(new ObjectMapper(), TEXT_HTML));
clientCodecConfigurer.customCodecs().registerWithDefaultConfig(new Jackson2JsonEncoder(new ObjectMapper(), TEXT_HTML));
}
目前我在使用新的 Spring 5 WebClient 时遇到问题,我需要一些帮助来解决这个问题。 问题是:
I request some url that returns json response with content type text/html;charset=utf-8.
But unfortunately I’m still getting an exception: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/html;charset=utf-8' not supported. So I can’t convert response to DTO.
对于请求,我使用以下代码:
Flux<SomeDTO> response = WebClient.create("https://someUrl")
.get()
.uri("/someUri").accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToFlux(SomeDTO.class);
response.subscribe(System.out::println);
顺便说一句,我在 accept header 中指向哪个类型并不重要,总是返回 text/html。那么我怎样才能让我的回复最终得到转换呢?
让服务发送 JSON 和 "text/html"
Content-Type 是相当不寻常的。
有两种处理方法:
- 配置 Jackson 解码器以解码
"text/html"
内容;查看WebClient.builder().exchangeStrategies(ExchangeStrategies)
设置方法 - 即时更改 "Content-Type" 响应 header
这是第二种解决方案的建议:
WebClient client = WebClient.builder().filter((request, next) -> next.exchange(request)
.map(response -> {
MyClientHttpResponseDecorator decorated = new
MyClientHttpResponseDecorator(response);
return decorated;
})).build();
class MyClientHttpResponseDecorator extends ClientHttpResponseDecorator {
private final HttpHeaders httpHeaders;
public MyClientHttpResponseDecorator(ClientHttpResponse delegate) {
super(delegate);
this.httpHeaders = new HttpHeaders(this.getDelegate().getHeaders());
// mutate the content-type header when necessary
}
@Override
public HttpHeaders getHeaders() {
return this.httpHeaders;
}
}
请注意,您应该只在该上下文中(针对该主机)使用该客户端。 如果可以的话,我强烈建议尝试修复服务器返回的奇怪 content-type。
如上一个回答所述,您可以使用 exchangeStrategies 方法,
示例:
Flux<SomeDTO> response = WebClient.builder()
.baseUrl(url)
.exchangeStrategies(ExchangeStrategies.builder().codecs(this::acceptedCodecs).build())
.build()
.get()
.uri(builder.toUriString(), 1L)
.retrieve()
.bodyToFlux( // .. business logic
private void acceptedCodecs(ClientCodecConfigurer clientCodecConfigurer) {
clientCodecConfigurer.customCodecs().encoder(new Jackson2JsonEncoder(new ObjectMapper(), TEXT_HTML));
clientCodecConfigurer.customCodecs().decoder(new Jackson2JsonDecoder(new ObjectMapper(), TEXT_HTML));
}
如果您需要设置 maxInMemorySize 以及 text/html 响应,请使用:
WebClient invoicesWebClient() {
return WebClient.builder()
.exchangeStrategies(ExchangeStrategies.builder().codecs(this::acceptedCodecs).build())
.build();
}
private void acceptedCodecs(ClientCodecConfigurer clientCodecConfigurer) {
clientCodecConfigurer.defaultCodecs().maxInMemorySize(BUFFER_SIZE_16MB);
clientCodecConfigurer.customCodecs().registerWithDefaultConfig(new Jackson2JsonDecoder(new ObjectMapper(), TEXT_HTML));
clientCodecConfigurer.customCodecs().registerWithDefaultConfig(new Jackson2JsonEncoder(new ObjectMapper(), TEXT_HTML));
}