Как мы преобразуем Flux<DataBuffer> из ClientHttpResponse в Mono<SomeDto>. Кроме того, можем ли мы получить доступ к MessageHeaders в bodyExtractor. Пожалуйста, предложите.
.handle(WebFlux.outboundGateway(apiUrl, webClient)
.httpMethod(POST)
.mappedRequestHeaders(CONTENT_TYPE)
.bodyExtractor((clientHttpResponse, context) -> validateAPIResponse(clientHttpResponse)))
private Mono<Object> validateAPIResponse(final ClientHttpResponse clientHttpResponse) {
var httpStatus = clientHttpResponse.getStatusCode();
// check for 500
if (httpStatus.is5xxServerError())
throw new SomeException(.......);
var responseMono = new Jackson2JsonDecoder().decodeToMono(clientHttpResponse.getBody(), ResolvableType.forClass(SomDto.class), null,
null);
// check for any other than 200
if (!httpStatus.is2xxSuccessful())
return responseMono.map(response -> {
throw new SomeOtherException(response.getSomeField(), httpStatus);
});





Вы можете просто делегировать BodyExtractors.toFlux(SomDto.class). Я не уверен, что вам действительно нужен кастом BodyExtractor, если просто expectedResponseType(SomDto.class) должно быть достаточно, чтобы вы произвели такой Mono. Не уверен также, что вам нужно самостоятельно обрабатывать эти ошибки: фреймворк делает достойную работу по этому вопросу.
Да, вы не можете получить доступ к MessageHeaders в этом контексте BodyExtractor, так как это не имеет ничего общего с обменом сообщениями.
Вы можете получить доступ к этим заголовкам немного ниже по течению, когда вы уже получили ответ от этого шлюза WebFlux. Если ваш ответ действительно сильно привязан к заголовкам, вам нужно подумать о создании общего ответа (например, Flux<DataBuffer>), а затем соответствующим образом преобразовать его в преобразователь, где вы уже получаете доступ ко всему сообщению запроса и его заголовкам.
См. также это в документах:
Spring Integration предоставляет
ClientHttpResponseBodyExtractorв качестве функции идентификации для создания (ниже по течению) всегоClientHttpResponseи любой другой возможной пользовательской логики.
Не могли бы вы предложить, позволяет ли фреймворк обрабатывать ответ WebFlux с помощью statusCode, а не через errorChannel?
Нет. Вы правы: разумное поведение по умолчанию — продолжить с 2xx и потерпеть неудачу с 5xx или 4xx. Итак, посмотрите, может ли мое другое предложение с этим ClientHttpResponseBodyExtractor помочь вам.
Пробовал пользовательский BodyExtractor, а также ClientHttpResponseBodyExtractor, в обоих случаях в конце, если это не статус 2xx, он переходит в errorChannel. Пример доступен по адресу github.com/syedyusufh/webflux-inboundgateway-error, вам нужна фиктивная конечная точка, чтобы вернуть 400. Пожалуйста, помогите
Здравствуйте @Artem, не могли бы вы попробовать образец, которым поделились, и дать нам несколько предложений, чтобы продолжить поток, не бросая WebFlux ответ на errorChannel
В настоящее время WebFluxRequestExecutingMessageHandler выполняет этот жесткий код: .onStatus(HttpStatusCode::isError, ClientResponse::createException). См. его JavaDocs: интересно, ExchangeFilterFunction, введенный в WebClient, предусмотренный для этого WebFluxRequestExecutingMessageHandler, поможет смягчить эту проблему. Например, вы можете преобразовать ClientResponse, чтобы у вас не было плохого кода состояния. Смотрите DefaultClientResponseBuilder.
Большое спасибо, мутация ClientResponse через ExchangeFilterFunction сделала свое дело вместе с пользовательским заголовком, чтобы узнать оригинал HttpStatus
Спасибо за подробное объяснение. Наш вариант использования — знать
HttpStatusCodeи действовать соответственно (фактически продолжать поток), а не отправлять сообщениеerrorChannel. С обычнымexpectedResponseType()любая серия, кроме 2xx, шла наerrorChannel, отсюда и необходимость кастомныхBodyExtractor