diff --git a/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/config/PolarisGatewayAutoConfiguration.java b/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/config/PolarisGatewayAutoConfiguration.java index cf8c1743..759e94c9 100644 --- a/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/config/PolarisGatewayAutoConfiguration.java +++ b/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/config/PolarisGatewayAutoConfiguration.java @@ -19,6 +19,8 @@ package com.tencent.cloud.polaris.gateway.config; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.http.ZuulServlet; +import com.tencent.cloud.polaris.gateway.core.route.DynamicRouteService; +import com.tencent.cloud.polaris.gateway.core.scg.filter.DynamicRouteScgFilter; import com.tencent.cloud.polaris.gateway.core.scg.filter.Metadata2HeaderScgFilter; import com.tencent.cloud.polaris.gateway.core.scg.filter.MetadataFirstScgFilter; import com.tencent.cloud.polaris.gateway.core.scg.filter.RateLimitScgFilter; @@ -73,6 +75,16 @@ public class PolarisGatewayAutoConfiguration { public GlobalFilter metadata2HeaderScgFilter() { return new Metadata2HeaderScgFilter(); } + + @Bean + public DynamicRouteService dynamicRouteService() { + return new DynamicRouteService(); + } + + @Bean + public DynamicRouteScgFilter dynamicRouteFilter() { + return new DynamicRouteScgFilter(); + } } } diff --git a/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/core/route/DynamicRouteService.java b/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/core/route/DynamicRouteService.java new file mode 100644 index 00000000..536ec069 --- /dev/null +++ b/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/core/route/DynamicRouteService.java @@ -0,0 +1,103 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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 com.tencent.cloud.polaris.gateway.core.route; + +import javax.annotation.Resource; +import org.springframework.cloud.gateway.event.RefreshRoutesEvent; +import org.springframework.cloud.gateway.route.RouteDefinition; +import org.springframework.cloud.gateway.route.RouteDefinitionWriter; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; +import reactor.core.publisher.Mono; + + +/** + * dynamic route service. + * + * @author bruceppeng + */ +public class DynamicRouteService implements ApplicationEventPublisherAware { + + @Resource + private RouteDefinitionWriter routeDefinitionWriter; + + private ApplicationEventPublisher publisher; + + private void notifyChanged() { + this.publisher.publishEvent(new RefreshRoutesEvent(this)); + } + + + /** + * add route. + * @param definition definition + * @return sucess + */ + public String add(RouteDefinition definition) { + routeDefinitionWriter.save(Mono.just(definition)).subscribe(); + notifyChanged(); + return "success"; + } + + + /** + * update route. + * @param definition definition + * @return sucess + */ + public String update(RouteDefinition definition) { + try { + this.routeDefinitionWriter.delete(Mono.just(definition.getId())); + } catch (Exception e) { + return "update fail,not find route routeId: " + definition.getId(); + } + try { + routeDefinitionWriter.save(Mono.just(definition)).subscribe(); + notifyChanged(); + return "success"; + } catch (Exception e) { + return "update route fail"; + } + + + } + + /** + * delete route. + * @param id id + * @return sucess + */ + public String delete(String id) { + try { + this.routeDefinitionWriter.delete(Mono.just(id)).subscribe(); + + notifyChanged(); + return "delete success"; + } catch (Exception e) { + e.printStackTrace(); + return "delete fail"; + } + + } + + @Override + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { + this.publisher = applicationEventPublisher; + } + +} \ No newline at end of file diff --git a/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/core/scg/filter/DynamicRouteScgFilter.java b/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/core/scg/filter/DynamicRouteScgFilter.java new file mode 100644 index 00000000..d3018884 --- /dev/null +++ b/spring-cloud-tencent-starters/spring-cloud-tencent-polaris-gateway/src/main/java/com/tencent/cloud/polaris/gateway/core/scg/filter/DynamicRouteScgFilter.java @@ -0,0 +1,103 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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 com.tencent.cloud.polaris.gateway.core.scg.filter; + +import com.tencent.cloud.metadata.constant.MetadataConstant; +import com.tencent.cloud.metadata.context.MetadataContextHolder; +import com.tencent.cloud.polaris.gateway.core.route.DynamicRouteService; +import java.net.URI; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.gateway.config.GatewayProperties; +import org.springframework.cloud.gateway.filter.FilterDefinition; +import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; +import org.springframework.cloud.gateway.route.RouteDefinition; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +/** + * Filter for implement dynamic route. + * + * @author kan peng + */ +public class DynamicRouteScgFilter implements WebFilter, Ordered { + + private static final Logger LOG = LoggerFactory.getLogger(DynamicRouteScgFilter.class); + + @Autowired + private DynamicRouteService dynamicRouteService; + + @Autowired + private GatewayProperties gatewayProperties; + + @Override + public int getOrder() { + return MetadataConstant.OrderConstant.FILTER_ORDER + 1; + } + + @Override + public Mono filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) { + + + ServerHttpRequest serverHttpRequest = serverWebExchange.getRequest(); + String requestPath = serverHttpRequest.getURI().getPath(); + String[] pathList = requestPath.split("/"); + String id = pathList[1]; + String path = String.format("/%s/**",id); + + //Check whether the route has been loaded + for(RouteDefinition routeDefinition: gatewayProperties.getRoutes()){ + if (id.equals(routeDefinition.getId())){ + return webFilterChain.filter(serverWebExchange); + } + } + + RouteDefinition definition = new RouteDefinition(); + definition.setId(id); + URI uri = URI.create("lb://"+id); + definition.setUri(uri); + + //Define the first assertion + PredicateDefinition predicate = new PredicateDefinition(); + predicate.setName("Path"); + + Map predicateParams = new HashMap<>(8); + predicateParams.put("pattern", path); + predicate.setArgs(predicateParams); + + //Define Filter + FilterDefinition filter = new FilterDefinition(); + filter.setName("StripPrefix"); + filter.addArg("parts","1"); + + definition.setFilters(Arrays.asList(filter)); + definition.setPredicates(Arrays.asList(predicate)); + dynamicRouteService.add(definition); + + return webFilterChain.filter(serverWebExchange); + } + +} \ No newline at end of file