1. 개요

HTTP 응답의 상태 코드를 사용하여 애플리케이션이 주어진 응답으로 다음에 무엇을 해야 하는지 결정하는 것이 종종 도움이 됩니다.

이 사용방법(예제)에서는 WebFlux의 WebClient 를 사용하여 REST 요청에서 반환된 상태 코드 및 Response body에 액세스하는 방법을 살펴보겠습니다 .

WebClient 는 Spring 5에 도입되었으며 RESTful 서비스를 호출하는 동안 비동기 I/O에 사용할 수 있습니다.

2. 사용 사례

다른 서비스에 대한 RESTful 호출을 수행할 때 애플리케이션은 일반적으로 반환된 상태 코드 를 사용하여 다른 기능을 트리거합니다. 일반적인 사용 사례에는 정상적인 오류 처리, 요청 재시도 트리거 및 사용자 오류 결정이 포함됩니다.

따라서 REST 호출을 할 때 응답 코드만 가져오는 것만으로는 충분하지 않은 경우가 많습니다. 때로는 Response body도 필요합니다.

다음 예제에서는 REST 클라이언트 WebClient 에서 Response body을 구문 분석하는 방법을 확인합니다 . 동작을 반환된 상태 코드에 연결하고 WebClient ,  onStatus 및  ExchangeFilterFunction 에서 제공하는 두 가지 상태 코드 추출 방법을 사용합니다 .

3. onStatus 사용

onStatus 는 WebClient 응답을 처리하는 데 사용할 수 있는 기본 제공 메커니즘입니다이를 통해 특정 응답 (예: 400, 500, 503 등) 또는 상태 범주(예: 4XX 및 5XX 등)를 기반으로 세분화된 기능을 적용할 수 있습니다 .

WebClient
  .builder()
  .build()
  .post()
  .uri("/some-resource")
  .retrieve()
  .onStatus(
    HttpStatus.INTERNAL_SERVER_ERROR::equals,
    response -> response.bodyToMono(String.class).map(Exception::new))

onStatus 메소드에는 두 개의 매개변수가 필요합니다 . 첫 번째는 상태 코드를 취하는 술어입니다. 두 번째 매개변수의 실행은 첫 번째 매개변수의 출력을 기반으로 합니다. 두 번째는 Mono 또는 Exception 에 대한 응답을 매핑하는 함수입니다 .

이 경우 INTERNAL_SERVER_ERROR (예: 500)가 표시되면 bodyToMono를 사용하여 본문을 가져온 다음 새 Exception 에 매핑합니다 .

다양한 상태 조건에 대한 기능을 제공할 수 있도록 onStatus 호출을 연결할 있습니다 .

Mono<String> response = WebClient
  .builder()
  .build()
  .post()
  .uri("some-resource")
  .retrieve()
  .onStatus( 
    HttpStatus.INTERNAL_SERVER_ERROR::equals,
    response -> response.bodyToMono(String.class).map(CustomServerErrorException::new)) 
  .onStatus(
    HttpStatus.BAD_REQUEST::equals,
    response -> response.bodyToMono(String.class).map(CustomBadRequestException::new))
  ... 
  .bodyToMono(String.class);

// do something with response

이제 onStatus 호출이 사용자 지정 예외에 매핑됩니다. 두 가지 오류 상태 각각에 대해 예외 유형을 정의했습니다. onStatus  메서드를 사용하면 선택한 모든 유형을 사용할 수 있습니다 .

4. ExchangeFilterFunction 사용

ExchangeFilterFunction 은 특정 상태 코드를 처리하고 Response body을 가져오는 또 다른 방법 입니다 . onStatus 와 달리 교환 필터는 유연하며 모든 부울 표현식을 기반으로 필터 기능에 적용됩니다.

ExchangeFilterFunction 의 유연성을 통해 onStatus 함수 와 동일한 범주 를 다룰 수 있습니다 .

먼저 ClientResponse 가 주어진 상태 코드를 기반으로 반환된 논리를 처리하는 메서드를 정의합니다 .

private static Mono<ClientResponse> exchangeFilterResponseProcessor(ClientResponse response) {
    HttpStatus status = response.statusCode();
    if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
        return response.bodyToMono(String.class)
          .flatMap(body -> Mono.error(new CustomServerErrorException(body)));
    }
    if (HttpStatus.BAD_REQUEST.equals(status)) {
        return response.bodyToMono(String.class)
          .flatMap(body -> Mono.error(new CustomBadRequestException(body)));
    }
    return Mono.just(response);
}

다음으로 필터를 정의하고 핸들러에 대한 메서드 참조를 사용합니다.

ExchangeFilterFunction errorResponseFilter = ExchangeFilterFunction
  .ofResponseProcessor(WebClientStatusCodeHandler::exchangeFilterResponseProcessor);

onStatus 호출과 마찬가지로 오류 발생 시 예외 유형에 매핑합니다 . 그러나 Mono.error  를 사용하면 이 예외ReactiveException으로 래핑됩니다. 오류를 처리 할 때 이 중첩을 염두에 두어야 합니다 .

이제 이것을 WebClient 의 인스턴스에 적용 하여 onStatus 연결 호출 과 동일한 효과를 얻습니다 .

Mono<String> response = WebClient
  .builder()
  .filter(errorResponseFilter)
  .build()
  .post()
  .uri("some-resource")
  .retrieve()
  .bodyToMono(String.class);

// do something with response

5. 결론

이 기사에서는 HTTP 상태 헤더를 기반으로 Response body을 가져오는 몇 가지 방법을 다루었습니다. 상태 코드를 기반으로 onStatus 메서드를 사용하면 특정 기능을 연결할 수 있습니다. 또한 필터 방법을 사용하여 범용 방법을 연결하여 모든 응답에 대한 사후 처리를 처리할 수 있습니다.

항상 그렇듯이 이 기사의 모든 코드는 GitHub 에서 찾을 수 있습니다 .

Generic footer banner