/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cn.exlive.exbooter.configure; import com.netflix.zuul.context.RequestContext; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.keyvalue.DefaultKeyValue; import org.apache.commons.lang.StringUtils; import org.springframework.cloud.netflix.zuul.filters.Route; import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import java.net.URI; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Random; import java.util.stream.Collectors; /** *
 *
 * Created by zhenqin.
 * User: zhenqin
 * Date: 2022/4/25
 * Time: 下午7:12
 *
 * 
* * @author zhenqin */ @Slf4j public class ApiRouteLocator extends SimpleRouteLocator { /** * zull 配置 */ final ZuulProperties properties; /** * 随机策略 */ final Random r = new Random(); public ApiRouteLocator(String servletPath, ZuulProperties properties) { super(servletPath, properties); this.properties = properties; } @Override protected Route getRoute(ZuulProperties.ZuulRoute route, String path) { if (route == null) { return null; } RequestContext ctx = RequestContext.getCurrentContext(); final String referer = ctx.getRequest().getHeader("Referer"); final Map> queryParams = Optional.ofNullable(ctx.getRequestQueryParams()).orElse(new HashMap<>()); String clusterId = queryParams.get("clusterId") == null ? null : StringUtils.join(queryParams.get("clusterId"), ","); if (StringUtils.isBlank(clusterId) && StringUtils.isNotBlank(referer)) { // 如果 URL 中没有,从 Referer 中获取 final String query = URI.create(referer).getQuery(); final Map kv = Arrays.stream(query.split("&")).filter(StringUtils::isNotBlank).map(it -> { final String[] split = it.split("="); return split.length > 1 ? new DefaultKeyValue(split[0], split[1]) : new DefaultKeyValue(split[0], ""); }).collect(Collectors.toMap(e -> (String)e.getKey(), e -> (String)e.getValue())); clusterId = kv.get("clusterId"); } log.info("clusterId: {} and referer: {}", clusterId, referer); String targetPath = path; String prefix = this.properties.getPrefix(); if (prefix.endsWith("/")) { prefix = prefix.substring(0, prefix.length() - 1); } if (path.startsWith(prefix + "/") && this.properties.isStripPrefix()) { targetPath = path.substring(prefix.length()); } if (route.isStripPrefix()) { int index = route.getPath().indexOf("*") - 1; if (index > 0) { String routePrefix = route.getPath().substring(0, index); targetPath = targetPath.replaceFirst(routePrefix, ""); prefix = prefix + routePrefix; } } Boolean retryable = this.properties.getRetryable(); if (route.getRetryable() != null) { retryable = route.getRetryable(); } final HashMap globalVariables = new HashMap<>(); // cluster: 1 path: /damp/aaa/bbb match to: http://localhost:8083/damp log.info("cluster: {} path: {} match to: {}", clusterId, path, route.getLocation()); // 如果包含逗号,说明有多个地址,需要负载均衡 if (route.getLocation().contains(",")) { final String[] segs = route.getLocation().split(","); // 随机策略 String loc = segs[r.nextInt(segs.length)]; // 替换路由地址 // loc = PlaceholderUtils.replacePlaceholders(loc, globalVariables, Constants.REGEX_VARIABLE); // log.info("loc->> " + loc); return new Route(route.getId(), targetPath, loc, prefix, retryable, route.isCustomSensitiveHeaders() ? route.getSensitiveHeaders() : null, route.isStripPrefix()); } // 替换路由地址 // String loc = PlaceholderUtils.replacePlaceholders(route.getLocation(), globalVariables, Constants.REGEX_VARIABLE); return new Route(route.getId(), targetPath, route.getLocation(), prefix, retryable, route.isCustomSensitiveHeaders() ? route.getSensitiveHeaders() : null, route.isStripPrefix()); } }