当前位置: 首页 > 知识库问答 >
问题:

如何在WebFilter中调用反应性endpoint

祁通
2023-03-14

我想实现一个WebFilter,它读取传入请求的特定头,用这个头的值调用一个GET请求到另一个反应RESTendpoint,然后用GET响应的值修改原始请求。

我想在WebFilter中实现这一点,因为我不想将此函数调用添加到我的@RestController中的每个函数中。

目前我有这个:

@Component
class ExampleWebFilter(val webClients: WebClients) : WebFilter {
    override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
        println(exchange.request.headers)
        println(exchange.request.path)
        println(exchange.response)

        val test = webClients.internalAuthServiceClient.get()
                .uri("/api/authorisation/v1/test")
                .header("authToken", "authToken123")
                .retrieve().bodyToMono(String::class.java)

        println(test)

        exchange.mutate().request(
                exchange.request.mutate().header("newheader", test).build()
        )
        return chain.filter(exchange)
    }
}

@Component
class WebClients() {
    val internalAuthServiceClient = WebClient.builder()
            .baseUrl("lb://auth-service")
            .build()
}

这显然现在不起作用。我的网络客户端正在返回单声道,所以我不能在我的Mutate()调用中直接使用它,因为这需要一个字符串。出于显而易见的原因,我也不能真正使网络客户端调用成为阻塞操作。

有人知道我怎么解决这个问题吗?

共有1个答案

闻人志
2023-03-14

我不使用kotlin,所以您必须进行转换,但这是在java中进行转换的方式。不过,我想情况会大致相同。

@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange,
                         WebFilterChain webFilterChain) {
    return webClients
            .internalAuthServiceClient
            .get()
            .uri("/api/authorisation/v1/test")
            .retrieve()
            .bodyToMono(String.class)
            //Gonna assume you tested the above and all works
            //If get bad response or any error really
            // then print error + return empty mono
            .onErrorResume(e -> {
                e.printStackTrace();
                return Mono.empty();
            })
            //Map the header AFTER a response
            //only maps if Mono is not empty
            .map(header -> {
                serverWebExchange
                        .getRequest()
                        .mutate()
                        .header("web-filter", header);
                return serverWebExchange;
            })
            //return unchanged serverWebExchange if empty Mono
            .defaultIfEmpty(serverWebExchange)
            //Flatmap since filter returns Mono to prevent returning Mono<Mono<void>>
            .flatMap(webFilterChain::filter);
}

您所面临的问题是因为您试图以同步的方式进行操作,而您需要在收到WebClient的响应后映射标题。

 类似资料:
  • 我正在尝试解决这个问题:如何通过REST控制器用Spring(引导)重写URL?通过创建某种类型的“过滤器”来应用于每个传入的HTTP请求。 这个问题包含了一些答案,比如这个问题:Spring Boot添加了Http请求拦截器,但接口处理的是Javax'和,它们不如Spring引入的新类实用,即(请参阅下面代码中)出现在一个名称听起来很有前途的接口: 所以我的结尾是这样的: ...就像人们在做类似

  • 我遇到的问题是filter方法永远不会执行,并且上下文也没有设置。我已经确认Webfilter是在启动时加载的。还有什么需要让过滤器工作吗?

  • 我正在尝试制作一个反应式,它在实际服务器交换之前和之后执行内容(即处理请求的控制器代码): 对于返回Mono的简单GET请求,一切都按预期工作: 但是当控制器收到一个注释为的参数时,会发生一些真正意想不到的事情。例如,一个接受

  • 我使用Spring Boot 2.1. x与网络流量和安全性。我定义了一些类型的bean,它们被添加到MatcherSecurityWebFilterChain中。问题是,因为它们被定义为bean,所以它们也被添加在过滤链的末端,所以它们被执行两次。 对于Servlet应用程序,我们可以使用来避免这种情况: 对于反应性应用程序,什么是等效的?

  • 我对反应式编程有点陌生,我正在尝试组装以下组件:使用Java、Springboot 2、Webflux和reactor core,我想处理需要额外身份验证的非常特定的请求。因此,我通过一系列步骤实现了一个Web过滤器: 捕获请求的路径和方法。检查该组合是否存在,是否需要使用accessPointService进行特定身份验证。getAccessPointAuthorizationRequireme

  • 通过调用直接创建通量并在的lambada表达式中使用接收器,与使用提供的接收器有什么区别? 在一个Flux只发出几个事件的最小示例中,我可以 与使用 为了澄清一下:我知道我可以在这里使用,但我的用例实际上是在Spring的和Spring WebFlux之间建立一个桥梁,在这里我想为每个传入的特定资源SSE请求创建一个Flux,然后将事件发布到这个Flux。 另一方面,它有不能处理背压的局限性。因此