Как «подсмотреть», если у Flux есть исключение? - PullRequest
0 голосов
/ 26 октября 2018

Я использую Spring Webflux с контейнером сервлетов Tomcat ( spring-boot-starter-web + spring-boot-starter-webflux ) и хотел бы получить следующий результат:

Если поток сбоев немедленно завершается, я хотел бы отправить клиенту код ответа 400

В противном случае я хотел бы отправить код ответа 200 и передать поток

Я пробовал разные решения, но никто не работает. v1 и v2 не отправляют ожидаемый код ответа, если сценарий сбоя, v3 не передает поток, является счастливым сценарием.

Я хотел бы «подсмотреть» исключение на failFlux и вызвать исключение перед отправкой кода ответа 200

@RequestMapping(produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public class X {
 Flux<String> happyFlux = Flux.generate(s -> s.next("x"));  
 Flux<String> failFlux = Flux.error(new ResponseStatusException(BAD_REQUEST));

 //ok: flux is streamed

 @RequestMapping("/v1/happy")
 Flux<String> v1Happy() {
    return happyFlux;
 }

 //nok: http status code is 200

 @RequestMapping("/v1/fail")
 Flux<String> v1Fail() {
    return failFlux;
 }

 //ok: flux is streamed

 @RequestMapping("/v2/happy")
 Mono<ResponseEntity<Flux<String>>> v2Happy() {
    return Mono.just(ResponseEntity.ok().body(happyFlux));
 }

 //nok: http status code is 200

 @RequestMapping("/v2/fail")
 Mono<ResponseEntity<Flux<String>>> v2Fail() {
    return Mono.just(ResponseEntity.ok().body(failFlux));
 }

 //nok: flux is not streamed but collected on server side

 @RequestMapping("/v3/happy")
 Mono<ResponseEntity<List<String>>> v3Happy() {
    return happyFlux.collectList().map(ResponseEntity::ok);
 }

 //ok: http status code is 400

 @RequestMapping("/v3/fail")
 Mono<ResponseEntity<List<String>>> v3Fail() {
    return failFlux.collectList().map(ResponseEntity::ok);
 }

PS. Что интересно, v1 и v2 работает с netty (только spring-boot-starter-webflux ).

Обновление

Я думаю, что "подглядывание" Флюса невозможно. Чем я на самом деле лучше, так это обработкой потока в Spring для стека сервлетов: https://jira.spring.io/browse/SPR-17440

1 Ответ

0 голосов
/ 27 октября 2018

Я бы посоветовал не использовать collectList (), так как это противоречит цели создания потока.Я считаю, что вы должны получить 500 в случае сообщения об исключении.

Например, проверьте приведенный ниже код.

public Mono<ServerResponse> listPeople(ServerRequest request) {
    int error = 10/0;
    Flux<Person> peopleFlux = this.repository.allPeople();
    peopleFlux = withDelay(peopleFlux);

    return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM).body(peopleFlux, Person.class);


}

Оператор

int error = 10/0;

вызывает исключение 500, а в клиенте я получаю 500. Если я закомментирую оператор ошибки, то получу 200. Итак, пожалуйста, поделитесьВы кодируете, если не получаете 500. Обратите внимание, что если ошибка возникает после того, как сервер начал возвращать отдельные события в потоке, то это не будет 500. Вам следует использовать HTTP 207. https://httpstatuses.com/207

...