Soul网关源码阅读(八)—— WebFlux过滤器

概要

上一篇我们分析了从客户端发起http请求到我们soul网关,网关是如何通过WebClientPlugin插件来进行转发的,这一篇我们继续深入讨论一下这过程中网关具体还干了其他什么事情,或者说可以干什么事情。

有时候一个http请求进来,我们需要对它做特殊处理,对在请求或者响应中添加一些业务逻辑(类似SpringMvc中filter和interceptor的功能),在webflux中有应该如何做呢?

答案就是使用过滤器

这一篇我们将介绍WebFilter的设计及作用,以及我们的Soul网关利用它来做了些什么事情。

WebFlux过滤器

过滤器的使用在Web应用程序中非常普遍,因为它们为我们提供了一种在不更改端点的情况下修改请求或响应的方法。

在本篇中,我们将介绍使用WebFlux框架实现过滤器功能的主要方法。

这篇我们将不涉及WebFlux框架本身的详细信息,如果你对此还不熟悉,可以参考之前两篇的内容:

Soul网关源码阅读(六)—— Soul网关之WebFlux

Soul网关源码阅读(七)—— http请求转发流程分析

定义路由端点

我们首先创建一些endpoints,我们使用基于注释和编程的方式各实现一个,以此来考虑如何实现基于两种不同端点类型的过滤方式。

基于注释控制器来创建端点:

@GetMapping(path = "/users/{name}")
public Mono<String> getName(@PathVariable String name) {
    
    
    return Mono.just(name);
}

对于端点功能,我们必须首先创建一个handler处理器:

@Component
public class PlayerHandler {
    
    
    public Mono<ServerResponse> getName(ServerRequest request) {
    
    
        Mono<String> name = Mono.just(request.pathVariable("name"));
        return ok().body(name, String.class);
    }
}

以及路由器映射配置:

@Bean
public RouterFunction<ServerResponse> route(PlayerHandler playerHandler) {
    
    
    return RouterFunctions
      .route(GET("/players/{name}"), playerHandler::getName)
      .filter(new ExampleHandlerFilterFunction());
}

由此我们分别用注释和编程的方式定义了两个路由端点:/users/{name}和/players/{name}。

定义拦截器

WebFlux框架提供了两种方式的过滤器:WebFilter和HandlerFilterFuntions。

它们之间的主要区别在于,WebFilter会对所有的路由端点生效,而HandlerFilterFuntion只对router中绑定了filter的起效。

也就是WebFilter是对全router起效,而HandlerFilterFuntion对绑定了filter的编程式router起效。

WebFilter

我们实现一个WebFilter来向响应添加新的header。因此,所有响应都应具有以下行为:

@Component
public class ExampleWebFilter implements WebFilter {
    
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    
    
        exchange.getResponse().getHeaders().add("web-filter","web-filter-test");
        return chain.filter(exchange);
    }
}

HandlerFilterFuntionn

这里我们实现当path请求参数name等于“test”时,将HTTP状态设置为FORBIDDEN

@Component
public class ExampleHandlerFilterFunction implements HandlerFilterFunction<ServerResponse, ServerResponse> {
    
    
    @Override
    public Mono<ServerResponse> filter(ServerRequest serverRequest, HandlerFunction<ServerResponse> handlerFunction) {
    
    
        if (serverRequest.pathVariable("name").equalsIgnoreCase("test")) {
    
    
            return ServerResponse.status(FORBIDDEN).build();
        }
        return handlerFunction.handle(serverRequest);
    }
}

测试

使用postman分别对/users/{name}和/players/{name}端点进行测试。

  • 可以看到所有请求的header里面都有web-filter -> web-filter-test。
  • 而对绑定了ExampleHandlerFilterFunction的/players/test才起效。

Soul网关中的那些过滤器

(明天补充)

结束语

今天分析了WebFlux中拦截器的用法,熟练掌握拦截器对我们构建系统架构时显得更加游刃有余。

猜你喜欢

转载自blog.csdn.net/u010084384/article/details/113065790