Spring 5 WebClient调用接口乱码问题排查处理

使用Spring的Reactive WebClient对三方接口进行调用,发现请求数据不能正常返回。由于此三方接口有严格的请求Header校验,怀疑是header没有传正确。

HttpClient httpClient = HttpClient.create();
eactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
WebClient client = WebClient.builder().clientConnector(connector).build();

Flux flux = client.post()
    .uri(URI.create(TEST_URL))
    .header(HttpHeaders.ACCEPT,"*/*")
    .header(HttpHeaders.ACCEPT_LANGUAGE,"zh-CN,en-US;q=0.7,en;q=0.3")
    .header(HttpHeaders.ACCEPT_ENCODING,"gzip,deflate,sdch")
    .header(HttpHeaders.CONTENT_TYPE,"application/x-www-form-urlencoded; charset=UTF-8")
    .header(HttpHeaders.HOST,"target.com")
    .header(HttpHeaders.USER_AGENT,UserAgents.randomUserAgent())
    .retrieve()
    .onStatus(HttpStatus::isError, response -> {
        throw new RuntimeException(response.statusCode().getReasonPhrase());
    })
    .bodyToFlux(String.class)
    .timeout(Duration.ofSeconds(5))
    .onErrorResume(throwable -> Flux.just("Error Request: "+throwable.getMessage()));

通过抓包发现果然设置的header没有生效。查看WebClient方法,发现设置多个header时不能调用header()进行设置,而是调用headers()。

Flux flux = client.post()
    .uri(URI.create(TEST_URL))
    .headers((header)->{
        header.set(HttpHeaders.ACCEPT,"*/*");
        header.set(HttpHeaders.ACCEPT_LANGUAGE,"zh-CN,en-US;q=0.7,en;q=0.3");
        header.set(HttpHeaders.ACCEPT_ENCODING,"gzip,deflate,sdch");
        header.set(HttpHeaders.CONNECTION,"keep-alive");
        header.set(HttpHeaders.CONTENT_TYPE,"application/x-www-form-urlencoded; charset=UTF-8");
        header.set(HttpHeaders.HOST,"target.com");
        header.set(HttpHeaders.USER_AGENT,UserAgents.randomUserAgent());
    })
    .retrieve()
    .onStatus(HttpStatus::isError, response -> {
        throw new RuntimeException(response.statusCode().getReasonPhrase());
    })
    .bodyToFlux(String.class)
    .timeout(Duration.ofSeconds(5))
    .onErrorResume(throwable -> Flux.just("Error Request: "+throwable.getMessage()));

由于业务需要,我在此处每次需要对header设置不同的值。如果不需要,可以对WebClient的header进行统一默认设置。

至此,接口能够正常请求并响应数据了。但是响应的数据打印却是乱码。

第一反应是返回数据编码问题,将WebClient接收数据修改为字节数组bodyToFlux(byte[].class),手动再对字节数据指定UTF-8字符集转换为String,发现仍是乱码。

然而奇怪的是之前使用Apache HttpClient相同的请求打印结果却显示正常,没有乱码。抓取两种客户端请求包分析,发现请求参数和响应完全相同。抓包工具Fidder中对响应体都会提示一个“响应数据已编码,点击进行解码“。突然想起请求头中包含gzip。怀疑响应数据是因为进行了gzip压缩,导致WebClient打印出来时乱码。

于是将代码中请求头的ACCEPT_ENCODING中的gzip去掉。再次请求,发现响应打印正常,不再乱码。

但是要开启gzip怎么办呢?查阅WebClient相关文档,只需完成以下配置即可:

HttpClient httpClient = HttpClient.create().compress(true);

你可能感兴趣的:(Spring 5 WebClient调用接口乱码问题排查处理)