简体   繁体   English

如何从 Spring 中提取响应 header 和状态码 5 WebClient ClientResponse

[英]How to extract response header & status code from Spring 5 WebClient ClientResponse

I am new to Spring Reactive framework & trying to convert Springboot 1.5.x code into Springboot 2.0.我是 Spring Reactive 框架的新手,正在尝试将 Springboot 1.5.x 代码转换为 Springboot 2.0。 I need to return response header after some filtering, body & status code from Spring 5 WebClient ClientResponse.经过一些过滤后,我需要返回响应 header,来自 Spring 的正文和状态代码 5 WebClient ClientResponse。 I do not want to use block() method as it will convert it into sync call.我不想使用 block() 方法,因为它会将其转换为同步调用。 I am able to get responsebody pretty easily using bodyToMono.我可以使用 bodyToMono 轻松获得 responsebody。 Also, I am getting status code, headers & body if I am just returning ClientResponse but I need to process response based on statusCode & header parameters.此外,如果我只是返回 ClientResponse,我将获得状态代码、标头和正文,但我需要根据 statusCode 和 header 参数处理响应。 I tried subscribe, flatMap etc. but nothing works.我试过订阅、平面地图等,但没有任何效果。

Eg - Below code will return response Body例如 - 下面的代码将返回响应正文

Mono<String> responseBody =  response.flatMap(resp -> resp.bodyToMono(String.class));

But similar paradigm is not working to get statusCode & Response headers.但是类似的范例无法获取 statusCode 和 Response 标头。 Can someone help me in extracting statusCode & header parameters using Spring 5 reactive framework.有人可以帮助我使用 Spring 5 反应框架提取 statusCode 和 header 参数。

You can use the exchange function of webclient eg您可以使用 webclient 的交换功能,例如

Mono<String> reponse = webclient.get()
.uri("https://stackoverflow.com")
.exchange()
.doOnSuccess(clientResponse -> System.out.println("clientResponse.headers() = " + clientResponse.headers()))
.doOnSuccess(clientResponse -> System.out.println("clientResponse.statusCode() = " + clientResponse.statusCode()))
.flatMap(clientResponse -> clientResponse.bodyToMono(String.class));

then you can convert bodyToMono etc然后你可以转换 bodyToMono 等

I needed to check the response details(headers, status, etc) and body as well.我还需要检查响应详细信息(标题、状态等)和正文。

The only way I was able to do it was by using .exchange() with two subscribe() as the following example:我能够做到的唯一方法是使用.exchange()和两个subscribe()作为以下示例:

    Mono<ClientResponse> clientResponse = WebClient.builder().build()
            .get().uri("https://stackoverflow.com")
            .exchange();

    clientResponse.subscribe((response) -> {

        // here you can access headers and status code
        Headers headers = response.headers();
        HttpStatus stausCode = response.statusCode();

        Mono<String> bodyToMono = response.bodyToMono(String.class);
        // the second subscribe to access the body
        bodyToMono.subscribe((body) -> {

            // here you can access the body
            System.out.println("body:" + body);

            // and you can also access headers and status code if you need
            System.out.println("headers:" + headers.asHttpHeaders());
            System.out.println("stausCode:" + stausCode);

        }, (ex) -> {
            // handle error
        });
    }, (ex) -> {
        // handle network error
    });

I hope it helps.我希望它有帮助。 If someone knows a better way to do it, please let us know.如果有人知道更好的方法,请告诉我们。

For status code you can try this:对于状态代码,您可以尝试以下操作:

Mono<HttpStatus> status = webClient.get()
                .uri("/example")
                .exchange()
                .map(response -> response.statusCode());

For headers:对于标题:

Mono<HttpHeaders> result = webClient.get()
                .uri("/example")
                .exchange()
                .map(response -> response.headers().asHttpHeaders());

After Spring Boot 2.4.x / Spring 5.3, WebClient exchange method is deprecated in favor of retrieve , so you have to get the headers and response status using ResponseEntity like the following example:在 Spring Boot 2.4.x / Spring 5.3 之后,WebClient exchange方法被弃用,取而代之的是retrieve ,因此您必须使用 ResponseEntity 获取标头和响应状态,如下例所示:

webClient
        .method(HttpMethod.POST)
        .uri(uriBuilder -> uriBuilder.path(loginUrl).build())
        .bodyValue(new LoginBO(user, passwd))
        .retrieve()
        .toEntity(LoginResponse.class)
        .filter(
            entity ->
                entity.getStatusCode().is2xxSuccessful()
                    && entity.getBody() != null
                    && entity.getBody().isLogin())
        .flatMap(entity -> Mono.justOrEmpty(entity.getHeaders().getFirst(tokenHeader)));

You can configure spring boot >= 2.1.0 to log request and response if you are using the WebClient :如果您使用WebClient您可以配置 spring boot >= 2.1.0 来记录请求和响应:

spring.http.log-request-details: true
logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions: TRACE

As desribed in the sprint boot docs , if you want headers to be logged, too, you have to add正如sprint boot docs 中所描述的,如果您也希望记录标题,则必须添加

Consumer<ClientCodecConfigurer> consumer = configurer ->
    configurer.defaultCodecs().enableLoggingRequestDetails(true);

WebClient webClient = WebClient.builder()
    .exchangeStrategies(ExchangeStrategies.builder().codecs(consumer).build())
    .build();

But be aware that this can log sensitve information.但请注意,这可能会记录敏感信息。

 httpClient
            .get()
            .uri(url)
            .retrieve()
            .toBodilessEntity()
            .map(reponse -> Tuple2(reponse.statusCode, reponse.headers))

As discussed above, the exchange has been deprecated so we are using retrieve().如上所述,交换已被弃用,因此我们使用了retrieve()。 This is how I'm returning the code after making a request.这就是我在提出请求后返回代码的方式。

public HttpStatus getResult() {
    WebClient.ResponseSpec response = client
            .get()
            .uri("/hello")
            .accept(MediaType.APPLICATION_JSON)
            .retrieve();

    return Optional.of(response.toBodilessEntity().block().getStatusCode()).get();
}

You can use flatMap to extract the object from Mono您可以使用flatMap从 Mono 中提取Mono

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM