文章背景图

Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.3) 之 RouteToRequestUrlFilter

2026-01-31
1
-
- 分钟
|

摘要: 原创出处 http://www.iocoder.cn/Spring-Cloud-Gateway/filter-route-to-request/ 「芋道源码」欢迎转载,保留摘要,谢谢!

本文主要基于 Spring-Cloud-Gateway 2.0.X M4

阅读源码最好的方式,是使用 IDEA 进行调试 Spring Cloud Gateway 源码,不然会一脸懵逼。

1. 概述

本文主要分享 RouteToRequestUrlFilter 的代码实现

RouteToRequestUrlFilter 根据匹配的 Route ,计算请求的地址。注意,这里的地址指的是 URL ,而不是 URI

😈 RouteToRequestUrlFilter 的代码十分少,所以这会是一篇简单的文章。


推荐 Spring Cloud 书籍

2. RouteToRequestUrlFilter

org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter ,代码如下 :

public class RouteToRequestUrlFilter implements GlobalFilter, Ordered {

	private static final Log log = LogFactory.getLog(RouteToRequestUrlFilter.class);
	public static final int ROUTE_TO_URL_FILTER_ORDER = 10000;

	@Override
	public int getOrder() {
		return ROUTE_TO_URL_FILTER_ORDER;
	}

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
	    // 获得 Route
		Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
		if (route == null) {
			return chain.filter(exchange);
		}
		log.trace("RouteToRequestUrlFilter start");
		// 拼接 requestUrl
		URI requestUrl = UriComponentsBuilder.fromHttpRequest(exchange.getRequest())
				.uri(route.getUri())
				.build(true) // encoded=true
				.toUri();
		// 设置 requestUrl 到 GATEWAY_REQUEST_URL_ATTR {@link RewritePathGatewayFilterFactory}
		exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
		// 提交过滤器链继续过滤
		return chain.filter(exchange);
	}

}

Route.uri

Request.uri

requestUrl

http://bin.org:80

http://127.0.0.1:8080/test/segment

http://httpbin.org:80/123

http://bin.org:80/123

http://127.0.0.1:8080/test/segment

http://httpbin.org:80/test/segment

  • 为什么会导致覆盖的情况呢 ?答案在 UriComponentsBuilder#uri(URI) 方法,代码如下 :

    public UriComponentsBuilder uri(URI uri) {
    	Assert.notNull(uri, "URI must not be null");
    	this.scheme = uri.getScheme();
    	if (uri.isOpaque()) {
    		this.ssp = uri.getRawSchemeSpecificPart();
    		resetHierarchicalComponents();
    	}
    	else {
    		if (uri.getRawUserInfo() != null) {
    			this.userInfo = uri.getRawUserInfo();
    		}
    		if (uri.getHost() != null) {
    			this.host = uri.getHost();
    		}
    		if (uri.getPort() != -1) {
    			this.port = String.valueOf(uri.getPort());
    		}
    		if (StringUtils.hasLength(uri.getRawPath())) {
    			this.pathBuilder = new CompositePathComponentBuilder();
    			this.pathBuilder.addPath(uri.getRawPath());
    		}
    		if (StringUtils.hasLength(uri.getRawQuery())) {
    			this.queryParams.clear();
    			query(uri.getRawQuery());
    		}
    		resetSchemeSpecificPart();
    	}
    	if (uri.getRawFragment() != null) {
    		this.fragment = uri.getRawFragment();
    	}
    	return this;
    }
    • 第 18 至 21 行 :当 uri 参数有 Path 时,新建一个 CompositePathComponentBuilder ,因此原有的 this.pathBuilder覆盖了。

  • 第 25 行 :设置 requestUrlGATEWAY_REQUEST_URL_ATTR 。后面 Routing 相关的 GatewayFilter 会通过该属性,发起请求。

  • 第 27 行 :提交过滤器链继续过滤。注意,这里不需要创建的 ServerWebExchange 。

评论交流

文章目录