ApiRouteLocator.java 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package cn.exlive.exbooter.configure;
  18. import com.netflix.zuul.context.RequestContext;
  19. import lombok.extern.slf4j.Slf4j;
  20. import org.apache.commons.collections.keyvalue.DefaultKeyValue;
  21. import org.apache.commons.lang.StringUtils;
  22. import org.springframework.cloud.netflix.zuul.filters.Route;
  23. import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
  24. import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
  25. import java.net.URI;
  26. import java.util.Arrays;
  27. import java.util.HashMap;
  28. import java.util.List;
  29. import java.util.Map;
  30. import java.util.Optional;
  31. import java.util.Random;
  32. import java.util.stream.Collectors;
  33. /**
  34. * <pre>
  35. *
  36. * Created by zhenqin.
  37. * User: zhenqin
  38. * Date: 2022/4/25
  39. * Time: 下午7:12
  40. *
  41. * </pre>
  42. *
  43. * @author zhenqin
  44. */
  45. @Slf4j
  46. public class ApiRouteLocator extends SimpleRouteLocator {
  47. /**
  48. * zull 配置
  49. */
  50. final ZuulProperties properties;
  51. /**
  52. * 随机策略
  53. */
  54. final Random r = new Random();
  55. public ApiRouteLocator(String servletPath, ZuulProperties properties) {
  56. super(servletPath, properties);
  57. this.properties = properties;
  58. }
  59. @Override
  60. protected Route getRoute(ZuulProperties.ZuulRoute route, String path) {
  61. if (route == null) {
  62. return null;
  63. }
  64. RequestContext ctx = RequestContext.getCurrentContext();
  65. final String referer = ctx.getRequest().getHeader("Referer");
  66. final Map<String, List<String>> queryParams = Optional.ofNullable(ctx.getRequestQueryParams()).orElse(new HashMap<>());
  67. String clusterId = queryParams.get("clusterId") == null ? null : StringUtils.join(queryParams.get("clusterId"), ",");
  68. if (StringUtils.isBlank(clusterId) && StringUtils.isNotBlank(referer)) {
  69. // 如果 URL 中没有,从 Referer 中获取
  70. final String query = URI.create(referer).getQuery();
  71. final Map<String, String> kv = Arrays.stream(query.split("&")).filter(StringUtils::isNotBlank).map(it -> {
  72. final String[] split = it.split("=");
  73. return split.length > 1 ? new DefaultKeyValue(split[0], split[1]) : new DefaultKeyValue(split[0], "");
  74. }).collect(Collectors.toMap(e -> (String)e.getKey(), e -> (String)e.getValue()));
  75. clusterId = kv.get("clusterId");
  76. }
  77. log.info("clusterId: {} and referer: {}", clusterId, referer);
  78. String targetPath = path;
  79. String prefix = this.properties.getPrefix();
  80. if (prefix.endsWith("/")) {
  81. prefix = prefix.substring(0, prefix.length() - 1);
  82. }
  83. if (path.startsWith(prefix + "/") && this.properties.isStripPrefix()) {
  84. targetPath = path.substring(prefix.length());
  85. }
  86. if (route.isStripPrefix()) {
  87. int index = route.getPath().indexOf("*") - 1;
  88. if (index > 0) {
  89. String routePrefix = route.getPath().substring(0, index);
  90. targetPath = targetPath.replaceFirst(routePrefix, "");
  91. prefix = prefix + routePrefix;
  92. }
  93. }
  94. Boolean retryable = this.properties.getRetryable();
  95. if (route.getRetryable() != null) {
  96. retryable = route.getRetryable();
  97. }
  98. final HashMap<String, String> globalVariables = new HashMap<>();
  99. // cluster: 1 path: /damp/aaa/bbb match to: http://localhost:8083/damp
  100. log.info("cluster: {} path: {} match to: {}", clusterId, path, route.getLocation());
  101. // 如果包含逗号,说明有多个地址,需要负载均衡
  102. if (route.getLocation().contains(",")) {
  103. final String[] segs = route.getLocation().split(",");
  104. // 随机策略
  105. String loc = segs[r.nextInt(segs.length)];
  106. // 替换路由地址
  107. // loc = PlaceholderUtils.replacePlaceholders(loc, globalVariables, Constants.REGEX_VARIABLE);
  108. // log.info("loc->> " + loc);
  109. return new Route(route.getId(),
  110. targetPath,
  111. loc,
  112. prefix,
  113. retryable,
  114. route.isCustomSensitiveHeaders() ? route.getSensitiveHeaders() : null,
  115. route.isStripPrefix());
  116. }
  117. // 替换路由地址
  118. // String loc = PlaceholderUtils.replacePlaceholders(route.getLocation(), globalVariables, Constants.REGEX_VARIABLE);
  119. return new Route(route.getId(),
  120. targetPath,
  121. route.getLocation(),
  122. prefix,
  123. retryable,
  124. route.isCustomSensitiveHeaders() ? route.getSensitiveHeaders() : null,
  125. route.isStripPrefix());
  126. }
  127. }