mike-neckのブログ

Java or Groovy or Swift or Golang

Mono<Void> は常に empty

当然といえば当然ですが、意外と気づかない。

例えば、特定の条件を満たさないとリクエストを処理しないような WebFilter を記述する。

@Bean
WebFilter webFilter() {
  return (exchange, chain) -> {
    Optional<String> requestDate = extractRequestDate(exchange);
    return Mono.justOrEmpty(requestDate)
        .flatMap(date -> Mono.defer(() -> chain.filter(exchange)))
        .switchIfEmpty(() -> forbidden(exchange));
  };
}

このような感じで何らかのヘッダーの値がある場合は処理を行った結果を返すが、ない場合は 403 Forbidden を返すみたいな WebFilter を書いたのだが、 これは常に 403 Forbidden を返し続ける。

WebFilterChain#filter(ServerWebExchange)Mono<Void> を返すが、タイトルにあるように Mono<Void> は(Voidインスタンスが作れないため)常に empty になる

ここでは、 Mono を連鎖させるのではなく、 Optional の値によって取り回すほうがよい

@Bean
WebFilter webFilter() {
  return (exchange, chain) -> {
    Optional<String> requestDate = extractRequestDate(exchange);
    return requestDate
        .map(date -> Mono.defer(() -> chain.filter(exchange)))
        .orElseGet(() -> forbidden(exchange));
  };
}