美文网首页来到JavaEE
Spring Cloud Gateway那些内置的Attribu

Spring Cloud Gateway那些内置的Attribu

作者: giafei | 来源:发表于2018-08-04 07:54 被阅读1425次

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());
        };
    }

相关文章

网友评论

    本文标题:Spring Cloud Gateway那些内置的Attribu

    本文链接:https://www.haomeiwen.com/subject/juupvftx.html