gateway filter

默认 filter

默认的有 38 个,分为5组:请求头、请求参数(查询字符串)、响应头、前缀和路径、其他,作用都不是很大,挑几个举个例

# 请求和响应 filter
- id: test_my_consumer
  uri: http://localhost:8082
  predicates:
    - Path=/feign/**
  filters:
    - AddRequestHeader=customer-header1,value1 # 请求头自动添加 customer-header1,值为 value1
    - AddRequestHeader=customer-header2,value2 # 请求头自动添加 customer-header2,值为 value2
    - RemoveRequestHeader=User-Agent # 移除请求头参数 User-Agent
    - SetRequestHeader=Content-Type,application/json;charset=UTF-8 # 修改请求头参数
    - AddRequestParameter=username,milk # url 查询字符串增加参数 username,值为 milk(如果请求url已经有username了,这里就不再添加了)
    - RemoveRequestParameter=userid # url 查询字符串增加参数移除 userid
    - AddResponseHeader=customer-response-header1,response1
    - RemoveResponseHeader=Content-Type
    - SetResponseHeader=Date,2099-01-01
    
    
# 路径前缀 filter(最终还是一致的,页面访问 /user/1 实际访问的是 /feign/user/1,作用是隐藏服务端真实地址)
- id: test_my_consumer2
  uri: http://localhost:8083
  predicates:
    # - Path=/feign/user/** 真实地址 /feign/user/**
    - Path=/user/** # 现在改为 /user/**
  filters:
    - PrefixPath=/fiegn # 加个前缀,页面访问 /user/**,实际访问的是  /feign/user/**

自定义过滤器

不说和 RoutePredicate 一摸一样,至少可以说是大差不差

/**
 * 类名也必须 GatewayFilterFactory 结尾,前面的就是自定义 filter 的名称。这里 My 就是 filter 的名称
 */ 
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {

    public MyGatewayFilterFactory(){
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(MyGatewayFilterFactory.Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            //如果 url 包含 username 参数就放行,不然就返回 404
            if (request.getQueryParams().containsKey(config.getProperty())){
                return chain.filter(exchange);
            }else {
                exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
                return exchange.getResponse().setComplete();
            }
        };
    }

    // 启用短促配置,自动映射配置文件的值到 property
    @Override
    public List<String> shortcutFieldOrder() {
        return List.of("property");
    }

    @Getter
    @Setter
    public static class Config
    {
        private String property; // 对应配置文件 property 的参数的值
    }
}

配置文件,结合上面的自定义 filter 代码,全部的含义是:1,/feign/user/** 请求会应用 My 这个过滤器;2,配置文件中的 username 将会映射到过滤器的 property 上;3,过滤器内部获取 url 参数,如果有 username 参数就放行,不然就响应 404

- id: test_my_consumer
  uri: http://localhost:8082
  predicates:
    - Path=/feign/user/** 
  filters:
    - My=username # 短促配置,不用显示指定 property 参数,自动把 username 映射到 property

自定义全局过滤器

注意这是全局过滤器,yaml 不需要配置

@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        HttpHeaders headers = exchange.getRequest().getHeaders();
        if (headers.isEmpty()){
            throw new RuntimeException("请求头为空");
        }
        if (!headers.containsKey("access-token")){
            throw new RuntimeException("请求头没有access-token");
        }
        String token = headers.getFirst("access-token");
        if (StringUtils.hasText(token)){
            throw new RuntimeException("请求头access-token为空");
        }
        // 到 redis 验证,token 是否合法
        if (!exist(token)){
            throw new RuntimeException("access-token不合法");
        }
        // 返回过滤器(请求都会应用这个过滤器)
        return chain.filter(exchange);
    }

    /**
     * 数字越小,优先级越高
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
posted @ 2024-07-19 13:54  CyrusHuang  阅读(2)  评论(0编辑  收藏  举报