使用 RxJava3Adapter 到 return RxJava Single 时,无法在 WebFlux Controller 中检索 Principal。你能解释一下是什么打破了反应器链吗?

Can't retrieve Principal in WebFlux Controller when using RxJava3Adapter to return a RxJava Single. Can you explain what's breaking the Reactor Chain?

我的 WebFlux 控制器:

import reactor.adapter.rxjava.RxJava3Adapter;
import reactor.core.publisher.Mono;
import io.reactivex.rxjava3.core.Single;

@RestController
@RequestMapping("/test")
public class MyController {

  @GetMapping("/mono")
  public Mono<String> getMono(ServerWebExchange exchange) {
    return exchange.getPrincipal()
      .map(principal -> principal.getName())
      .switchIfEmpty(Mono.just("no principal"));
  }

  @GetMapping("/single")
  public Single<String> getSingle(ServerWebExchange exchange) {
    return RxJava3Adapter.monoToSingle(exchange.getPrincipal()
      .map(principal -> principal.getName())
      .switchIfEmpty(Mono.just("no principal")));
  }

}

在上面的代码中,getMono returns 校长的名字,而 getSingle returns “没有校长”。

我正在尝试了解原因。这可能与 RxJava3Adapter 有关。我不确定它是否将反应堆发布者变成了“热门”发布者,因为我觉得这是一种竞争条件。

我的 Curl 命令(失败)

curl --request GET \
--url http://localhost:8080/test/single \
--header 'authorization: Bearer XXXX' \

简单的解决方案就是将我们所有的 API 转换为 Reactor 类型,但这不是一件容易的事。 RxJava 类型在我们的代码中无处不在,而不仅仅是在控制器中。我们将不得不重写数百个文件。所以我想在提议走那条路之前更好地理解这一点。

我将这个问题作为 issue 发布到 reactor github 页面。我发现在 Single 的情况下 Principal 丢失的原因是因为我们在跳转到 RxJava 链时丢失了 Reactor Context,它没有 Context 的概念。该 Reactor 上下文包含 SecurityContext,其中包含 Principal。 反应堆团队证实了这一点。