1

本文主要研究一下spring cloud的RequestHeaderToRequestUriGatewayFilter

GatewayAutoConfiguration

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java

@Configuration
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore(HttpHandlerAutoConfiguration.class)
@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
    //......
    @Bean
    public RequestHeaderToRequestUriGatewayFilterFactory requestHeaderToRequestUriGatewayFilterFactory() {
        return new RequestHeaderToRequestUriGatewayFilterFactory();
    }
    //......
}

RequestHeaderToRequestUriGatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/RequestHeaderToRequestUriGatewayFilterFactory.java

/**
 * This filter changes the request uri by a request header
 *
 * @author Toshiaki Maki
 */
public class RequestHeaderToRequestUriGatewayFilterFactory extends
        AbstractChangeRequestUriGatewayFilterFactory<AbstractGatewayFilterFactory.NameConfig> {
    private final Logger log = LoggerFactory
            .getLogger(RequestHeaderToRequestUriGatewayFilterFactory.class);

    public RequestHeaderToRequestUriGatewayFilterFactory() {
        super(NameConfig.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(NAME_KEY);
    }

    @Override
    protected Optional<URI> determineRequestUri(ServerWebExchange exchange,
            NameConfig config) {
        String requestUrl = exchange.getRequest().getHeaders().getFirst(config.getName());
        return Optional.ofNullable(requestUrl).map(url -> {
            try {
                return new URL(url).toURI();
            }
            catch (MalformedURLException | URISyntaxException e) {
                log.info("Request url is invalid : url={}, error={}", requestUrl,
                        e.getMessage());
                return null;
            }
        });
    }
}
  • 主要是继承了AbstractChangeRequestUriGatewayFilterFactory
  • 这里重写了determineRequestUri方法,根据配置的header取出url

AbstractChangeRequestUriGatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/AbstractChangeRequestUriGatewayFilterFactory.java

/**
 * This filter changes the request uri by
 * {@link #determineRequestUri(ServerWebExchange, T)} logic.
 *
 * @author Toshiaki Maki
 */
public abstract class AbstractChangeRequestUriGatewayFilterFactory<T>
        extends AbstractGatewayFilterFactory<T> {
    private final int order;

    public AbstractChangeRequestUriGatewayFilterFactory(Class<T> clazz, int order) {
        super(clazz);
        this.order = order;
    }

    public AbstractChangeRequestUriGatewayFilterFactory(Class<T> clazz) {
        this(clazz, RouteToRequestUrlFilter.ROUTE_TO_URL_FILTER_ORDER + 1);
    }

    protected abstract Optional<URI> determineRequestUri(ServerWebExchange exchange,
            T config);

    public GatewayFilter apply(T config) {
        return new OrderedGatewayFilter((exchange, chain) -> {
            Optional<URI> uri = this.determineRequestUri(exchange, config);
            uri.ifPresent(u -> {
                Map<String, Object> attributes = exchange.getAttributes();
                attributes.put(GATEWAY_REQUEST_URL_ATTR, u);
            });
            return chain.filter(exchange);
        }, this.order);
    }
}
这里就是取出url,设置GATEWAY_REQUEST_URL_ATTR,然后GlobalFilter里头会根据这个属性取出url出来使用

实例

spring:
  cloud:
    gateway:
      enabled: true
      discovery:
        locator:
          enabled: true
      routes:
      - id: demo
        uri: http://wwww.baidu.com
        predicates:
        - Path=/baidu/**
        filters:
        - RequestHeaderToRequestUri=X-New-Url
比如这里设置了根据X-New-Url来进行新的url路由,那么执行下面这段代码,则请求/baidu的则会转向请求163的
curl -i -H "X-New-Url: http://news.163.com" localhost:10000/baidu

小结

RequestHeaderToRequestUriGatewayFilter实现的功能就是根据配置文件指定的header来读取新的路由的url。比较强大,可以用在灰度、生产定位问题等场景上。

doc


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...