将客户端响应转换为服务器响应

Fri*_*ing 5 spring-webflux

我正在尝试在 REST 服务器和调用客户端应用程序之间编写一种代理,以便通过向 REST 调用添加属性来强制执行隐私。

我不想检查来自服务器的响应,我只想将其传递给客户端。

我想用 spring-webflux 做到这一点,因为我希望通过事件驱动的方法节省一些 CPU。但我完全被困住了。

这是,我尝试:

public Mono<ServerResponse> select(ServerRequest request) {
  return request.principal().flatMap((principal) -> {
    return WebClient.create(solrUrl).get().uri(f -> {
              URI u = f.path(request.pathVariable("a")).path("/b/").queryParams(queryModifier.modify(principal, request.pathVariable("collection"), request.queryParams()).block()).build();
              if (debug) {
                log.debug("Calling {}", u);
              }
              return u;
            })
        .exchange()
          .flatMap((ClientResponse mapper) -> {
            BodyBuilder bodyBuilder = ServerResponse.status(mapper.statusCode());
            bodyBuilder.body(BodyInserters.fromDataBuffers(mapper.bodyToFlux(DataBuffer.class)));
            bodyBuilder.headers(c -> mapper.headers().asHttpHeaders().forEach((name, value) -> c.put(name, value)));
              //.body(DefaultserverreBodyInserters.fromPublisher(mapper.bodyToMono(DataBuffer.class), DataBuffer.class)));
              //.body(BodyInserters.fromDataBuffers(mapper.bodyToFlux(DataBuffer.class))));
              //.body(BodyInserters.fromDataBuffers(mapper.body(BodyExtractors.toDataBuffers()))));
              //.body(mapper.bodyToMono(String.class), String.class));
              //.build());
            return bodyBuilder.build();
          });
  });
}
Run Code Online (Sandbox Code Playgroud)

我通过 RouterFunction 将它绑定到面向 REST API 的客户端:

@Configuration
public class VoiceRouterFunctions {

  @Bean
  public RouterFunction<ServerResponse> route(ClientPropertiesRequestHandler handler) {
    return RouterFunctions.route(RequestPredicates.GET("/v3/{a}/select")
        .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), handler::select);
  }
}
Run Code Online (Sandbox Code Playgroud)

响应是 200 - OK,身体什么也没有。有任何想法吗?

ESa*_*ala 2

以下是对您的问题的解释,希望能帮助您理解为什么会出现这种情况。

您的问题中的错误如下:该BodyBuilder.body(...)方法实际上构建返回a Mono<ServerResponse>,但它不会修改构建器。如果您查看构建器的源代码,您可以看到这一点。

通过查看您的代码更容易理解:

BodyBuilder bodyBuilder = ServerResponse.status(...);  // 1
bodyBuilder.body(...);                                 // 2
bodyBuilder.headers(...);                              // 3
return bodyBuilder.build();                            // 4
Run Code Online (Sandbox Code Playgroud)

发生的情况是这样的:在第 1 行,您创建了一个构建器,在第 2 行,您添加了一个主体并构建了它,但您没有将结果存储在变量中(哎呀!),然后在第 3 行,您将标头添加到初始结构中。 builder,它没有主体,因为该body(...)函数不会修改构建器,并且在第 4 行,您构建并返回空构建器。所以,在你的情况下,第 2 行什么也不做。

body(...)正如您在答案中偶然发现的,解决方案是在最后调用该函数,它应该是最后一个!

下面的例子也可以工作。注意行的新顺序。

BodyBuilder bodyBuilder = ServerResponse.status(...);  // 1
bodyBuilder.headers(...);                              // 3
return bodyBuilder.body(...);                          // 2
Run Code Online (Sandbox Code Playgroud)

  • 这在失败场景中不起作用,例如 http 响应代码为 401、404 等 (2认同)