Spring Cloud Gateway会使用ServerHttpRequest的attribute在filter之间存储和传递数据,大部分都封装在ServerWebExchangeUtils类中。
PRESERVE_HOST_HEADER_ATTRIBUTE
是否将request的host http头透传到被代理的服务中
public class PreserveHostHeaderGatewayFilterFactory extends AbstractGatewayFilterFactory {
public GatewayFilter apply() {
return apply(o -> {});
}
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
exchange.getAttributes().put(PRESERVE_HOST_HEADER_ATTRIBUTE, true);
return chain.filter(exchange);
};
}
}
//NettyRoutingFilter 省略其它代码
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//只保留关键代码
ServerHttpRequest request = exchange.getRequest();
boolean preserveHost = exchange.getAttributeOrDefault(PRESERVE_HOST_HEADER_ATTRIBUTE, false);
return this.httpClient.request(method, url, req -> {
final HttpClientRequest proxyRequest = req.options(NettyPipeline.SendOptions::flushOnEach)
.headers(httpHeaders)
.chunkedTransfer(chunkedTransfer)
.failOnServerError(false)
.failOnClientError(false);
if (preserveHost) {
String host = request.getHeaders().getFirst(HttpHeaders.HOST);
proxyRequest.header(HttpHeaders.HOST, host);
}
return proxyRequest.sendHeaders()
.send(request.getBody().map(dataBuffer ->
((NettyDataBuffer)dataBuffer).getNativeBuffer()));
});
}
URI_TEMPLATE_VARIABLES_ATTRIBUTE
处理Restful格式的url中的
//PathRoutePredicateFactory 关键代码
public Predicate<ServerWebExchange> apply(Config config) {
synchronized (this.pathPatternParser) {
config.pathPattern = this.pathPatternParser.parse(config.pattern);
}
return exchange -> {
PathContainer path = parsePath(exchange.getRequest().getURI().getPath());
boolean match = config.pathPattern.matches(path);
traceMatch("Pattern", config.pathPattern.getPatternString(), path, match);
if (match) {
PathMatchInfo uriTemplateVariables = config.pathPattern.matchAndExtract(path);
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
return true;
} else {
return false;
}
};
}
//SetPathGatewayFilterFactory 关键代码
public GatewayFilter apply(Config config) {
//只保留关键代码
UriTemplate uriTemplate = new UriTemplate(config.template);
return (exchange, chain) -> {
PathMatchInfo variables = exchange.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
Map<String, String> uriVariables;
if (variables != null) {
uriVariables = variables.getUriVariables();
} else {
uriVariables = Collections.emptyMap();
}
URI uri = uriTemplate.expand(uriVariables);
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, uri);
ServerHttpRequest request = req.mutate()
.path(uri.getRawPath())
.build();
return chain.filter(exchange.mutate().request(request).build());
};
}
CLIENT_RESPONSE_ATTR
传递被代理的http请求的response
NettyRoutingFilter 或 WebClientHttpRoutingFilter 负责写入此attribute
NettyRoutingFilter 或 NettyWriteResponseFilter 负责消费此attribute
GATEWAY_ROUTE_ATTR
本次请求的 Route 对象
//RoutePredicateHandlerMapping 关键代码
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName());
return lookupRoute(exchange)
.flatMap((Function<Route, Mono<?>>) r -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
return Mono.just(webHandler);
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
})));
}
GATEWAY_SCHEME_PREFIX_ATTR 与 GATEWAY_REQUEST_URL_ATTR
本次请求的目的url
//RouteToRequestUrlFilter 关键代码
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
if (route == null) {
return chain.filter(exchange);
}
log.trace("RouteToRequestUrlFilter start");
URI uri = exchange.getRequest().getURI();
boolean encoded = containsEncodedParts(uri);
URI routeUri = route.getUri();
if (hasAnotherScheme(routeUri)) {
// this is a special url, save scheme to special attribute
// replace routeUri with schemeSpecificPart
exchange.getAttributes().put(GATEWAY_SCHEME_PREFIX_ATTR, routeUri.getScheme());
routeUri = URI.create(routeUri.getSchemeSpecificPart());
}
URI requestUrl = UriComponentsBuilder.fromUri(uri)
.uri(routeUri)
.build(encoded)
.toUri();
//最开始赋值,后面的过滤器都是修改 此过滤器之前都是直接修改request
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
return chain.filter(exchange);
}
//NettyRoutingFilter
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
final String url = requestUrl.toString();
return this.httpClient.request(method, url, req -> {
发送请求
}).doOnNext(res -> {
接收数据
}).then(chain.filter(exchange));
}
GATEWAY_ORIGINAL_REQUEST_URL_ATTR
记录请求url变更的历史
//ServerWebExchangeUtils 关键代码
public static void addOriginalRequestUrl(ServerWebExchange exchange, URI url) {
exchange.getAttributes().computeIfAbsent(GATEWAY_ORIGINAL_REQUEST_URL_ATTR, s -> new LinkedHashSet<>());
LinkedHashSet<URI> uris = exchange.getRequiredAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
uris.add(url);
}
//PrefixPathGatewayFilterFactory
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest req = exchange.getRequest();
addOriginalRequestUrl(exchange, req.getURI()); //调用
//变更request
String newPath = config.prefix + req.getURI().getRawPath();
ServerHttpRequest request = req.mutate().path(newPath).build();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI());
return chain.filter(exchange.mutate().request(request).build());
};
}
//其它调用类同
GATEWAY_HANDLER_MAPPER_ATTR
本次请求的handler的类的名称
//RoutePredicateHandlerMapping 关键代码
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName());
return lookupRoute(exchange)
.flatMap((Function<Route, Mono<?>>) r -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
//设置路由对象
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
return Mono.just(webHandler);
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
})));
}
GATEWAY_PREDICATE_ROUTE_ATTR 与 WEIGHT_ATTR
路由选择的时候会用
//RoutePredicateHandlerMapping 关键代码
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
return this.routeLocator.getRoutes()
.filterWhen(route -> {
// add the current route we are testing
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, route.getId()); //如果重写了路由的predicate 的apply
return route.getPredicate().apply(exchange);
})
.map(route -> {
validateRoute(route, exchange);
return route;
});
}
//WeightRoutePredicateFactory
public Predicate<ServerWebExchange> apply(WeightConfig config) {
return exchange -> {
Map<String, String> weights = exchange.getAttributeOrDefault(WEIGHT_ATTR,
Collections.emptyMap());
String routeId = exchange.getAttribute(GATEWAY_PREDICATE_ROUTE_ATTR);
String group = config.getGroup();
if (weights.containsKey(group)) {
String chosenRoute = weights.get(group);
return routeId.equals(chosenRoute);
}
return false;
};
}
GATEWAY_ALREADY_ROUTED_ATTR
默认的路由处理器成功的处理了请求时会写此属性,要自定义路由处理器,阻止默认的处理器时可用这个属性
//ServerWebExchangeUtils 关键代码
/**
* Used when a routing filter has been successfully call. Allows users to write custom
* routing filters that disable built in routing filters.
*/
public static void setAlreadyRouted(ServerWebExchange exchange) {
exchange.getAttributes().put(GATEWAY_ALREADY_ROUTED_ATTR, true);
}
public static boolean isAlreadyRouted(ServerWebExchange exchange) {
return exchange.getAttributeOrDefault(GATEWAY_ALREADY_ROUTED_ATTR, false);
}
//NettyRoutingFilter
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
String scheme = requestUrl.getScheme();
if (isAlreadyRouted(exchange) || (!"http".equals(scheme) && !"https".equals(scheme))) {
return chain.filter(exchange);
}
setAlreadyRouted(exchange);
//省略后面的处理逻辑
}
//省略其它的处理器,调用方法类同
GATEWAY_ALREADY_PREFIXED_ATTR
目前只有PrefixPath过滤器在用 见文档
//PrefixPathGatewayFilterFactory 关键代码
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
boolean alreadyPrefixed = exchange.getAttributeOrDefault(GATEWAY_ALREADY_PREFIXED_ATTR, false);
if (alreadyPrefixed) {
return chain.filter(exchange);
}
exchange.getAttributes().put(GATEWAY_ALREADY_PREFIXED_ATTR, true);
ServerHttpRequest req = exchange.getRequest();
addOriginalRequestUrl(exchange, req.getURI());
String newPath = config.prefix + req.getURI().getRawPath();
ServerHttpRequest request = req.mutate()
.path(newPath)
.build();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI());
return chain.filter(exchange.mutate().request(request).build());
};
}
网友评论