diff --git a/src/main/java/ink/wgink/gateway/component/MongoRouteDefinitionRepository.java b/src/main/java/ink/wgink/gateway/component/MongoRouteDefinitionRepository.java index c644bf6..33f22d1 100644 --- a/src/main/java/ink/wgink/gateway/component/MongoRouteDefinitionRepository.java +++ b/src/main/java/ink/wgink/gateway/component/MongoRouteDefinitionRepository.java @@ -1,8 +1,7 @@ package ink.wgink.gateway.component; -import ink.wgink.gateway.consts.ISystemConst; import ink.wgink.gateway.dao.route.IRouteDao; -import ink.wgink.gateway.filter.local.CommonFilters; +import ink.wgink.gateway.filter.local.CommonFiltersDefinition; import ink.wgink.gateway.pojo.route.Route; import ink.wgink.gateway.util.UUIDUtil; import org.springframework.cloud.gateway.filter.FilterDefinition; @@ -98,13 +97,11 @@ public class MongoRouteDefinitionRepository implements RouteDefinitionRepository * @return */ private List listFilterDefinition(Route route) { - CommonFilters commonFilters = new CommonFilters(); + CommonFiltersDefinition commonFiltersDefinition = new CommonFiltersDefinition(); // 定义过滤器 List filterDefinitions = new ArrayList<>(); - // 添加重写过滤 - filterDefinitions.add(commonFilters.rewriteFilterDefinition(route)); - // 去除前缀 -// filterDefinitions.add(commonFilters.setPathFilterDefinition(route)); + // 重写响应头中的location解决重定向问题 + filterDefinitions.add(commonFiltersDefinition.rewriteLocationResponseHeader(route)); return filterDefinitions; } diff --git a/src/main/java/ink/wgink/gateway/consts/ISystemConst.java b/src/main/java/ink/wgink/gateway/consts/ISystemConst.java index 2d9c9ca..1aa199e 100644 --- a/src/main/java/ink/wgink/gateway/consts/ISystemConst.java +++ b/src/main/java/ink/wgink/gateway/consts/ISystemConst.java @@ -20,5 +20,6 @@ public interface ISystemConst { String ADMIN_ROUTER_PREFIX = "/wg"; String PAGE_LOGIN = "/wg/login.html"; String ROUTE_PREFIX = "/gw"; + String ROOT_PATH_PREFIX = "/*"; } diff --git a/src/main/java/ink/wgink/gateway/filter/local/CommonFilters.java b/src/main/java/ink/wgink/gateway/filter/local/CommonFilters.java deleted file mode 100644 index f4c9e2d..0000000 --- a/src/main/java/ink/wgink/gateway/filter/local/CommonFilters.java +++ /dev/null @@ -1,55 +0,0 @@ -package ink.wgink.gateway.filter.local; - -import ink.wgink.gateway.consts.ISystemConst; -import ink.wgink.gateway.pojo.route.Route; -import org.springframework.cloud.gateway.filter.FilterDefinition; -import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory; -import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory; - -import java.util.HashMap; -import java.util.Map; - -/** - * When you feel like quitting. Think about why you started - * 当你想要放弃的时候,想想当初你为何开始 - * - * @ClassName: CommonFilters - * @Description: 通用过滤器 - * @Author: WangGeng - * @Date: 2021/4/24 20:31 - * @Version: 1.0 - **/ -public class CommonFilters { - - /** - * 重写过滤器 - * - * @param route - * @return - */ - public FilterDefinition rewriteFilterDefinition(Route route) { - FilterDefinition rewritePathFilterDefinition = new FilterDefinition(); - Map rewritePathFilterDefinitionMap = new HashMap<>(4); - rewritePathFilterDefinitionMap.put(RewritePathGatewayFilterFactory.REGEXP_KEY, ISystemConst.ROUTE_PREFIX + "/?(?.*)"); - rewritePathFilterDefinitionMap.put(RewritePathGatewayFilterFactory.REPLACEMENT_KEY, "/$\\{segment}"); - rewritePathFilterDefinition.setArgs(rewritePathFilterDefinitionMap); - rewritePathFilterDefinition.setName("RewritePath"); - return rewritePathFilterDefinition; - } - - /** - * 设置路径过滤器,去除前缀 - * - * @param route - * @return - */ - public FilterDefinition setPathFilterDefinition(Route route) { - FilterDefinition setPathFilterDefinition = new FilterDefinition(); - Map setPathFilterDefinitionMap = new HashMap<>(2); - setPathFilterDefinitionMap.put(SetPathGatewayFilterFactory.TEMPLATE_KEY, route.getPath().replaceFirst(ISystemConst.ROUTE_PREFIX, "/")); - setPathFilterDefinition.setArgs(setPathFilterDefinitionMap); - setPathFilterDefinition.setName("SetPath"); - return setPathFilterDefinition; - } - -} diff --git a/src/main/java/ink/wgink/gateway/filter/local/CommonFiltersDefinition.java b/src/main/java/ink/wgink/gateway/filter/local/CommonFiltersDefinition.java new file mode 100644 index 0000000..693c4ee --- /dev/null +++ b/src/main/java/ink/wgink/gateway/filter/local/CommonFiltersDefinition.java @@ -0,0 +1,72 @@ +package ink.wgink.gateway.filter.local; + +import ink.wgink.gateway.consts.ISystemConst; +import ink.wgink.gateway.pojo.route.Route; +import org.springframework.cloud.gateway.filter.FilterDefinition; +import org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: CommonFilters + * @Description: 通用过滤器 + * @Author: WangGeng + * @Date: 2021/4/24 20:31 + * @Version: 1.0 + **/ +public class CommonFiltersDefinition { + + /** + * 重写过滤器,将路径中的gw删除,暂时无用 + * + * @param route + * @return + */ + public FilterDefinition rewritePath(Route route) { + FilterDefinition rewritePath = new FilterDefinition(); + Map rewritePathMap = new HashMap<>(4); + rewritePathMap.put(RewritePathGatewayFilterFactory.REGEXP_KEY, ISystemConst.ROUTE_PREFIX + "/?(?.*)"); + rewritePathMap.put(RewritePathGatewayFilterFactory.REPLACEMENT_KEY, "/$\\{segment}"); + rewritePath.setArgs(rewritePathMap); + rewritePath.setName("RewritePath"); + return rewritePath; + } + + /** + * 设置路径过滤器,去除前缀,将路径中的gw删除,暂时无用 + * + * @param route + * @return + */ + public FilterDefinition setPath(Route route) { + FilterDefinition setPath = new FilterDefinition(); + Map setPathMap = new HashMap<>(2); + setPathMap.put(SetPathGatewayFilterFactory.TEMPLATE_KEY, route.getPath().replaceFirst(ISystemConst.ROUTE_PREFIX, "/")); + setPath.setArgs(setPathMap); + setPath.setName("SetPath"); + return setPath; + } + + /** + * 重写响应头中的地址信息 + * + * @param route + * @return + */ + public FilterDefinition rewriteLocationResponseHeader(Route route) { + FilterDefinition rewriteLocationResponse = new FilterDefinition(); + Map rewriteLocationResponseMap = new HashMap<>(2); + rewriteLocationResponseMap.put("stripVersionMode", RewriteLocationResponseHeaderGatewayFilterFactory.StripVersion.AS_IN_REQUEST.toString()); + rewriteLocationResponseMap.put("hostValue", "Location"); + rewriteLocationResponse.setName("RewriteLocationResponseHeader"); + return rewriteLocationResponse; + } + +} diff --git a/src/main/java/ink/wgink/gateway/filter/web/WebFluxFilter.java b/src/main/java/ink/wgink/gateway/filter/web/WebFluxFilter.java index 67a57c9..4165963 100644 --- a/src/main/java/ink/wgink/gateway/filter/web/WebFluxFilter.java +++ b/src/main/java/ink/wgink/gateway/filter/web/WebFluxFilter.java @@ -52,7 +52,7 @@ public class WebFluxFilter implements WebFilter { ServerHttpResponse serverHttpResponse = serverWebExchange.getResponse(); HttpHeaders headers = serverHttpResponse.getHeaders(); // 校验登录的路径,管理使用 - if(this.isUnPass(serverWebExchange)) { + if (this.isUnPass(serverWebExchange)) { // 直接放行的路径 if (this.isPass(serverWebExchange)) { return webFilterChain.filter(serverWebExchange); diff --git a/src/main/java/ink/wgink/gateway/handler/route/RouteHandler.java b/src/main/java/ink/wgink/gateway/handler/route/RouteHandler.java index 619c915..ac290f4 100644 --- a/src/main/java/ink/wgink/gateway/handler/route/RouteHandler.java +++ b/src/main/java/ink/wgink/gateway/handler/route/RouteHandler.java @@ -1,10 +1,14 @@ package ink.wgink.gateway.handler.route; +import ink.wgink.gateway.consts.ISystemConst; import ink.wgink.gateway.dao.route.IRouteDao; +import ink.wgink.gateway.exception.ParamsException; import ink.wgink.gateway.handler.BaseHandler; import ink.wgink.gateway.pojo.result.SuccessResult; import ink.wgink.gateway.pojo.route.Route; +import ink.wgink.gateway.util.RequestFieldCheckUtil; import ink.wgink.gateway.util.UUIDUtil; +import org.apache.commons.lang3.StringUtils; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.springframework.cloud.gateway.route.RouteDefinition; @@ -56,6 +60,10 @@ public class RouteHandler extends BaseHandler implements ApplicationEventPublish public Mono save(ServerRequest serverRequest) { Mono routeMono = serverRequest.bodyToMono(Route.class); return routeMono.flatMap(route -> { + RequestFieldCheckUtil.check(route); + if (route.getPath().startsWith(ISystemConst.ROOT_PATH_PREFIX)) { + return Mono.error(new ParamsException("根路径不能配置通配符")); + } setSave(route); return routeDao.save(route); }).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Flux.just(new SuccessResult()), SuccessResult.class)); @@ -86,10 +94,15 @@ public class RouteHandler extends BaseHandler implements ApplicationEventPublish Mono routeMono = serverRequest.bodyToMono(Route.class); return routeDao.findById(id).flatMap( route -> routeMono.flatMap(r -> { + RequestFieldCheckUtil.check(r); + if (r.getPath().startsWith(ISystemConst.ROOT_PATH_PREFIX)) { + return Mono.error(new ParamsException("根路径不能配置通配符")); + } route.setTitle(r.getTitle()); route.setSummary(r.getSummary()); route.setPath(r.getPath()); route.setUri(r.getUri()); + route.setTestPath(r.getTestPath()); setUpdate(route); return routeDao.save(route); }).then(ServerResponse.ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Flux.just(new SuccessResult()), SuccessResult.class)) diff --git a/src/main/java/ink/wgink/gateway/pojo/route/Route.java b/src/main/java/ink/wgink/gateway/pojo/route/Route.java index cf5fdaf..1ba1fc3 100644 --- a/src/main/java/ink/wgink/gateway/pojo/route/Route.java +++ b/src/main/java/ink/wgink/gateway/pojo/route/Route.java @@ -1,5 +1,6 @@ package ink.wgink.gateway.pojo.route; +import ink.wgink.gateway.annoation.CheckEmptyAnnotation; import ink.wgink.gateway.dao.route.IRouteDao; import ink.wgink.gateway.pojo.BasePOJO; import lombok.Data; @@ -24,9 +25,15 @@ import java.io.Serializable; public class Route extends BasePOJO implements Serializable { private static final long serialVersionUID = -4892456861969101733L; + @CheckEmptyAnnotation(name = "title") private String title; + @CheckEmptyAnnotation(name = "说明") private String summary; + @CheckEmptyAnnotation(name = "映射路径", verifyType = "path") private String path; + @CheckEmptyAnnotation(name = "被映射服务", verifyType = "url") private String uri; + @CheckEmptyAnnotation(name = "测试接口", verifyType = "path") + private String testPath; } diff --git a/src/main/java/ink/wgink/gateway/util/RegexUtil.java b/src/main/java/ink/wgink/gateway/util/RegexUtil.java index 765394e..d4d7820 100644 --- a/src/main/java/ink/wgink/gateway/util/RegexUtil.java +++ b/src/main/java/ink/wgink/gateway/util/RegexUtil.java @@ -36,9 +36,13 @@ public class RegexUtil { */ private static final Pattern PATTERN_EMAIL = Pattern.compile("^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$"); /** - * 邮箱 + * URL */ private static final Pattern PATTERN_URL = Pattern.compile("(^#)|(^http(s*):\\/\\/[^\\s]+)"); + /** + * 路径 + */ + private static final Pattern PATTERN_PATH = Pattern.compile("\\/[^\\s]*"); /** * 日期格式 */ @@ -164,6 +168,16 @@ public class RegexUtil { return PATTERN_URL.matcher(input).matches(); } + /** + * 判断PATH + * + * @param input + * @return + */ + public static boolean isPath(String input) { + return PATTERN_PATH.matcher(input).matches(); + } + /** * 判断日期 * @@ -311,8 +325,4 @@ public class RegexUtil { return path; } - public static void main(String[] args) { - System.out.println(isHhMmSs("1111111")); - } - } diff --git a/src/main/java/ink/wgink/gateway/util/RequestFieldCheckUtil.java b/src/main/java/ink/wgink/gateway/util/RequestFieldCheckUtil.java index df7b1e2..c4fdfca 100644 --- a/src/main/java/ink/wgink/gateway/util/RequestFieldCheckUtil.java +++ b/src/main/java/ink/wgink/gateway/util/RequestFieldCheckUtil.java @@ -229,6 +229,11 @@ public class RequestFieldCheckUtil { throw new ParamsException(String.format("%s格式非url格式", name)); } return; + } else if (StringUtils.equals("path", verifyType)) { + if (!RegexUtil.isPath(value)) { + throw new ParamsException(String.format("%s格式非路径格式", name)); + } + return; } else if (StringUtils.equals("number", verifyType)) { if (!NumberUtils.isNumber(value)) { throw new ParamsException(String.format("%s格式非数字格式", name)); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a2227cd..7a7865f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,6 +4,10 @@ spring: cloud: gateway: enabled: true + httpclient: + # 支持https转发 + ssl: + use-insecure-trust-manager: true data: mongodb: uri: mongodb://127.0.0.1:27017/gateway diff --git a/src/main/resources/static/wg/route/route/list.html b/src/main/resources/static/wg/route/route/list.html index 5f72762..e8b2f9e 100644 --- a/src/main/resources/static/wg/route/route/list.html +++ b/src/main/resources/static/wg/route/route/list.html @@ -127,6 +127,15 @@ return rowData; } }, + {field: 'testPath', width: 200, title: '测试接口', align: 'center', sort: true, + templet: function (row) { + var rowData = row[this.field]; + if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') { + return '-'; + } + return '点击测试'; + } + }, {field: 'gmtCreate', width: 180, title: '添加时间', align: 'center', sort: true, templet: function (row) { var rowData = row[this.field]; diff --git a/src/main/resources/static/wg/route/route/save.html b/src/main/resources/static/wg/route/route/save.html index 39620ba..bdb3198 100644 --- a/src/main/resources/static/wg/route/route/save.html +++ b/src/main/resources/static/wg/route/route/save.html @@ -36,14 +36,28 @@
-
直接访问网关的路径,路径中的变量用{}包含,/p2/{pq1}/{pq2}
+
+ 直接访问网关的路径
+ 支持通配符,如:p1/**,表示p1后的人和路径都匹配;
+ 路径中的变量用{}包含,如:/p2/{pq1}/{pq2} +
-
需要映射的服务器uri路径,如http://127.0.0.1:8080
+
+ 需要映射的服务器uri路径
+ 如:http://127.0.0.1:8080、http://www.baidu.com、https://www.baidu.com +
+
+
+
+ +
+ +
填写测试接口地址,如:/p1/a/b/c
diff --git a/src/main/resources/static/wg/route/route/update.html b/src/main/resources/static/wg/route/route/update.html index 1abc9b7..4c694cf 100644 --- a/src/main/resources/static/wg/route/route/update.html +++ b/src/main/resources/static/wg/route/route/update.html @@ -36,14 +36,28 @@
-
直接访问网关的路径,路径中的变量用{}包含,/p2/{pq1}/{pq2}
+
+ 直接访问网关的路径
+ 支持通配符,如:p1/**,表示p1后的人和路径都匹配;
+ 路径中的变量用{}包含,如:/p2/{pq1}/{pq2} +
-
需要映射的服务器uri路径,如http://127.0.0.1:8080
+
+ 需要映射的服务器uri路径
+ 如:http://127.0.0.1:8080、http://www.baidu.com、https://www.baidu.com +
+
+
+
+ +
+ +
填写测试接口地址,如:/p1/a/b/c