gateway filter

CyrusHuang發表於2024-09-05

預設 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;
    }
}

相關文章