From 7a24912c1df5a972f7b2bd18b337d6a26ecb86ea Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Mon, 21 Oct 2019 15:12:52 -0400 Subject: [PATCH] Removes RSocket support temporarily. Fixes gh-1366 Moved to https://github.com/spring-cloud-incubator/spring-cloud-rsocket --- pom.xml | 10 - spring-cloud-gateway-dependencies/pom.xml | 26 -- spring-cloud-gateway-rsocket/pom.xml | 40 -- .../pom.xml | 168 --------- .../rsocket/actuate/BrokerActuator.java | 129 ------- .../BrokerActuatorHandlerRegistration.java | 120 ------ .../gateway/rsocket/actuate/BrokerInfo.java | 138 ------- .../gateway/rsocket/actuate/RouteJoin.java | 175 --------- .../gateway/rsocket/actuate/RouteRemove.java | 121 ------ .../autoconfigure/BrokerProperties.java | 115 ------ .../GatewayRSocketAutoConfiguration.java | 196 ---------- ...atewayRSocketEnvironmentPostProcessor.java | 42 --- .../rsocket/cluster/ClusterJoinListener.java | 105 ------ .../rsocket/cluster/ClusterService.java | 116 ------ .../rsocket/cluster/RouteJoinListener.java | 64 ---- .../rsocket/core/AbstractGatewayRSocket.java | 106 ------ .../gateway/rsocket/core/GatewayExchange.java | 139 ------- .../gateway/rsocket/core/GatewayFilter.java | 24 -- .../rsocket/core/GatewayFilterChain.java | 53 --- .../rsocket/core/GatewayPredicate.java | 23 -- .../gateway/rsocket/core/GatewayRSocket.java | 225 ----------- .../rsocket/core/GatewayRSocketFactory.java | 100 ----- .../GatewayServerRSocketFactoryProcessor.java | 85 ----- .../rsocket/core/PendingRequestRSocket.java | 158 -------- .../core/PendingRequestRSocketFactory.java | 105 ------ .../rsocket/filter/AbstractFilterChain.java | 117 ------ .../filter/AbstractRSocketExchange.java | 31 -- .../gateway/rsocket/filter/FilterChain.java | 37 -- .../rsocket/filter/RSocketExchange.java | 70 ---- .../gateway/rsocket/filter/RSocketFilter.java | 52 --- .../metrics/MicrometerResponderRSocket.java | 249 ------------ ...MicrometerResponderRSocketInterceptor.java | 53 --- .../gateway/rsocket/route/DefaultRoute.java | 197 ---------- .../cloud/gateway/rsocket/route/Route.java | 41 -- .../cloud/gateway/rsocket/route/Routes.java | 61 --- .../rsocket/routing/LoadBalancerFactory.java | 97 ----- .../gateway/rsocket/routing/RoutingTable.java | 333 ---------------- .../rsocket/routing/RoutingTableRoutes.java | 172 --------- .../RoutingTableSocketAcceptorFilter.java | 55 --- .../socketacceptor/GatewaySocketAcceptor.java | 126 ------- .../SocketAcceptorExchange.java | 58 --- .../socketacceptor/SocketAcceptorFilter.java | 24 -- .../SocketAcceptorFilterChain.java | 45 --- .../SocketAcceptorPredicate.java | 23 -- .../SocketAcceptorPredicateFilter.java | 62 --- .../rsocket/support/AsyncPredicate.java | 50 --- .../main/resources/META-INF/spring.factories | 7 - .../BrokerActuatorIntegrationTests.java | 194 ---------- .../actuate/BrokerActuatorRegistrarTests.java | 50 --- .../GatewayRSocketAutoConfigurationTests.java | 84 ----- .../rsocket/cluster/ClusterServiceTests.java | 45 --- .../core/GatewayRSocketIntegrationTests.java | 95 ----- .../rsocket/core/GatewayRSocketTests.java | 321 ---------------- .../routing/RoutingTableRoutesTests.java | 69 ---- .../rsocket/routing/RoutingTableTests.java | 168 --------- .../GatewaySocketAcceptorTests.java | 247 ------------ .../SocketAcceptorPredicateFilterTests.java | 131 ------- .../gateway/rsocket/test/PingPongApp.java | 336 ----------------- .../test/SocketAcceptorFilterOrderTests.java | 49 --- .../src/test/resources/application.yml | 17 - .../pom.xml | 145 ------- .../gateway/rsocket/client/BrokerClient.java | 76 ---- .../BrokerClientConnectionListener.java | 78 ---- .../rsocket/client/ClientProperties.java | 180 --------- .../client/ClientRSocketRequester.java | 185 --------- .../client/ClientRSocketRequesterBuilder.java | 112 ------ ...GatewayRSocketClientAutoConfiguration.java | 123 ------ .../main/resources/META-INF/spring.factories | 3 - .../rsocket/client/ClientPropertiesTests.java | 64 ---- .../client/ClientRSocketRequesterTests.java | 108 ------ .../src/test/resources/application.yml | 12 - .../pom.xml | 161 -------- .../rsocket/common/autoconfigure/Broker.java | 90 ----- ...GatewayRSocketCommonAutoConfiguration.java | 73 ---- ...SocketCommonMetadataAutoConfiguration.java | 69 ---- .../rsocket/common/metadata/Forwarding.java | 220 ----------- .../rsocket/common/metadata/Metadata.java | 31 -- .../rsocket/common/metadata/RouteSetup.java | 228 ----------- .../rsocket/common/metadata/TagsMetadata.java | 356 ------------------ .../rsocket/common/metadata/WellKnownKey.java | 131 ------- .../main/resources/META-INF/spring.factories | 4 - .../metadata/ForwardingIntegrationTests.java | 72 ---- .../common/metadata/ForwardingTests.java | 75 ---- .../metadata/RouteSetupIntegrationTests.java | 72 ---- .../common/metadata/RouteSetupTests.java | 111 ------ .../common/metadata/TagsMetadataTests.java | 63 ---- .../rsocket/common/test/MetadataEncoder.java | 256 ------------- 87 files changed, 9447 deletions(-) delete mode 100644 spring-cloud-gateway-rsocket/pom.xml delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/pom.xml delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuator.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorHandlerRegistration.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerInfo.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/RouteJoin.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/RouteRemove.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/BrokerProperties.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketAutoConfiguration.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketEnvironmentPostProcessor.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterJoinListener.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterService.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/RouteJoinListener.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/AbstractGatewayRSocket.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayExchange.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayFilter.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayFilterChain.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayPredicate.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocket.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketFactory.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayServerRSocketFactoryProcessor.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/PendingRequestRSocket.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/PendingRequestRSocketFactory.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/AbstractFilterChain.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/AbstractRSocketExchange.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/FilterChain.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/RSocketExchange.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/RSocketFilter.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/metrics/MicrometerResponderRSocket.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/metrics/MicrometerResponderRSocketInterceptor.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/DefaultRoute.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/Route.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/Routes.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/LoadBalancerFactory.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTable.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableRoutes.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableSocketAcceptorFilter.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/GatewaySocketAcceptor.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorExchange.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorFilter.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorFilterChain.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicate.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicateFilter.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/support/AsyncPredicate.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorIntegrationTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorRegistrarTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketAutoConfigurationTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterServiceTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketIntegrationTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableRoutesTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/socketacceptor/GatewaySocketAcceptorTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicateFilterTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/test/PingPongApp.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/test/SocketAcceptorFilterOrderTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/resources/application.yml delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/pom.xml delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/BrokerClient.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/BrokerClientConnectionListener.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientProperties.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequester.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequesterBuilder.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/GatewayRSocketClientAutoConfiguration.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/java/org/springframework/cloud/gateway/rsocket/client/ClientPropertiesTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequesterTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/resources/application.yml delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/pom.xml delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/Broker.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/GatewayRSocketCommonAutoConfiguration.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/GatewayRSocketCommonMetadataAutoConfiguration.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/Forwarding.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/Metadata.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetup.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/TagsMetadata.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/WellKnownKey.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/ForwardingIntegrationTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/ForwardingTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetupIntegrationTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetupTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/TagsMetadataTests.java delete mode 100644 spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/test/MetadataEncoder.java diff --git a/pom.xml b/pom.xml index ee2610ab..09bf0403 100644 --- a/pom.xml +++ b/pom.xml @@ -129,7 +129,6 @@ spring-cloud-gateway-mvc spring-cloud-gateway-webflux spring-cloud-gateway-core - spring-cloud-gateway-rsocket spring-cloud-starter-gateway spring-cloud-gateway-sample docs @@ -179,15 +178,6 @@ false - - - jfrog-snapshots - JFRog Snapshots - https://oss.jfrog.org/artifactory/libs-snapshot - - true - - diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index f889bc75..3a43eddb 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -18,7 +18,6 @@ Spring Cloud Gateway Dependencies - 0.8.9 @@ -38,36 +37,11 @@ spring-cloud-gateway-core ${project.version} - - org.springframework.cloud - spring-cloud-gateway-rsocket - ${project.version} - - - org.springframework.cloud - spring-cloud-gateway-rsocket-common - ${project.version} - - - org.springframework.cloud - spring-cloud-gateway-rsocket-client - ${project.version} - - - org.springframework.cloud - spring-cloud-gateway-rsocket-broker - ${project.version} - org.springframework.cloud spring-cloud-starter-gateway ${project.version} - - org.roaringbitmap - RoaringBitmap - ${roaringbitmap.version} - diff --git a/spring-cloud-gateway-rsocket/pom.xml b/spring-cloud-gateway-rsocket/pom.xml deleted file mode 100644 index 8fbd9048..00000000 --- a/spring-cloud-gateway-rsocket/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - 4.0.0 - - org.springframework.cloud - spring-cloud-gateway - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-gateway-rsocket - Spring Cloud Gateway RSocket - Spring Cloud Gateway RSocket - pom - - - spring-cloud-gateway-rsocket-common - spring-cloud-gateway-rsocket-client - spring-cloud-gateway-rsocket-broker - - - diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/pom.xml b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/pom.xml deleted file mode 100644 index a9e50759..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/pom.xml +++ /dev/null @@ -1,168 +0,0 @@ - - - - - 4.0.0 - - org.springframework.cloud - spring-cloud-gateway-rsocket - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-gateway-rsocket-broker - Spring Cloud Gateway RSocket Broker - Spring Cloud Gateway RSocket Broker - - - - org.springframework.cloud - spring-cloud-gateway-rsocket-common - - - org.springframework.boot - spring-boot-starter-rsocket - - - org.springframework.boot - spring-boot-configuration-processor - true - - - io.rsocket - rsocket-core - - - io.rsocket - rsocket-micrometer - - - io.rsocket - rsocket-transport-netty - - - io.micrometer - micrometer-core - - - org.roaringbitmap - RoaringBitmap - - - org.springframework.boot - spring-boot-starter-actuator - test - - - org.projectlombok - lombok - test - - - org.springframework.boot - spring-boot-starter-test - test - - - io.projectreactor - reactor-test - test - - - org.springframework.cloud - spring-cloud-gateway-rsocket-common - ${project.version} - test-jar - test - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - -parameters - - - - - - default-compile - none - - - - default-testCompile - none - - - java-compile - compile - - compile - - - - java-test-compile - test-compile - - testCompile - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.1.0 - - - - test-jar - - - - - - - - - java8plus - - [1.8,2.0) - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - -parameters - - - - - - - - - diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuator.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuator.java deleted file mode 100644 index 688fdf04..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuator.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.actuate; - -import java.math.BigInteger; -import java.util.List; - -import io.rsocket.RSocket; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Mono; -import reactor.util.function.Tuple2; - -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.cluster.ClusterService; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable; -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.stereotype.Controller; - -@Controller -public class BrokerActuator { - - private static final Log log = LogFactory.getLog(BrokerActuator.class); - - /** - * Path for BrokerInfo actuator endpoint. - */ - public static final String BROKER_INFO_PATH = "actuator.gateway.brokerinfo"; - - /** - * Path for RouteJoin actuator endpoint. - */ - public static final String ROUTE_JOIN_PATH = "actuator.gateway.routejoin"; - - /** - * Path for RouteJoin actuator endpoint. - */ - public static final String ROUTE_REMOVE_PATH = "actuator.gateway.routeremove"; - - private final BrokerProperties properties; - - private final ClusterService clusterService; - - private final RoutingTable routingTable; - - public BrokerActuator(BrokerProperties properties, ClusterService clusterService, - RoutingTable routingTable) { - this.properties = properties; - this.clusterService = clusterService; - this.routingTable = routingTable; - } - - @MessageMapping("hello") - public Mono hello(String name) { - return Mono.just("Hello " + name); - } - - @MessageMapping(BROKER_INFO_PATH) - public BigInteger brokerInfo(BrokerInfo brokerInfo) { - log.info("BrokerInfo: " + brokerInfo); - clusterService.registerIncoming(brokerInfo); - return properties.getRouteId(); - } - - @MessageMapping(ROUTE_JOIN_PATH) - @SuppressWarnings("Duplicates") - public RouteJoin routeJoin(RouteJoin routeJoin) { - log.info("RouteJoin: " + routeJoin); - TagsMetadata findBrokerQuery = TagsMetadata.builder() - .routeId(routeJoin.getBrokerId().toString()).build(); - List> rSockets = routingTable - .findRSockets(findBrokerQuery); - - if (rSockets.size() != 1) { - // should only be one broker - if (log.isDebugEnabled()) { - log.debug("Expected 1 RSocket for broker: " + routeJoin.getBrokerId() - + ", found " + rSockets.size()); - } - return null; - } - RSocket brokerRSocket = rSockets.iterator().next().getT2(); - TagsMetadata.Builder tags = TagsMetadata.builder(); - // TODO: other tags. - // routeJoin.getTags().forEach(tags::with); - tags.routeId(routeJoin.getRouteId().toString()) - .serviceName(routeJoin.getServiceName()); - - TagsMetadata tagsMetadata = tags.build(); - routingTable.register(tagsMetadata, brokerRSocket); - - brokerRSocket.onClose().doOnSuccess(v -> { - if (log.isDebugEnabled()) { - log.debug("Broker closed, deregistering " + tagsMetadata); - } - routingTable.deregister(tagsMetadata); - }).doOnError(t -> { - if (log.isErrorEnabled()) { - log.error("Error received on broker, deregistering " + tagsMetadata, t); - } - routingTable.deregister(tagsMetadata); - }).subscribe(); - // TODO: keep track of disposable? - return routeJoin; - } - - @MessageMapping(ROUTE_REMOVE_PATH) - public boolean routeRemove(RouteRemove routeRemove) { - log.info("RouteRemove: " + routeRemove); - return routingTable.deregister(TagsMetadata.builder() - .routeId(routeRemove.getRouteId().toString()).build()); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorHandlerRegistration.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorHandlerRegistration.java deleted file mode 100644 index 9f10f161..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorHandlerRegistration.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.actuate; - -import java.util.concurrent.atomic.AtomicBoolean; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import io.rsocket.AbstractRSocket; -import io.rsocket.ConnectionSetupPayload; -import io.rsocket.Payload; -import io.rsocket.SocketAcceptor; -import io.rsocket.frame.SetupFrameFlyweight; -import io.rsocket.util.DefaultPayload; - -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable; -import org.springframework.context.SmartLifecycle; -import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.core.io.buffer.NettyDataBufferFactory; -import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; - -import static io.rsocket.metadata.WellKnownMimeType.APPLICATION_CBOR; -import static io.rsocket.metadata.WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA; - -public class BrokerActuatorHandlerRegistration implements SmartLifecycle { - - private final AtomicBoolean running = new AtomicBoolean(); - - private final RoutingTable routingTable; - - private final RSocketMessageHandler messageHandler; - - private final BrokerProperties properties; - - public BrokerActuatorHandlerRegistration(RoutingTable routingTable, - RSocketMessageHandler messageHandler, BrokerProperties properties) { - this.routingTable = routingTable; - this.messageHandler = messageHandler; - this.properties = properties; - } - - @Override - public void start() { - if (this.running.compareAndSet(false, true)) { - ConnectionSetupPayload connectionSetupPayload = getConnectionSetupPayload(); - SocketAcceptor responder = this.messageHandler.responder(); - responder.accept(connectionSetupPayload, new AbstractRSocket() { - }).subscribe(rSocket -> { - TagsMetadata tagsMetadata = TagsMetadata.builder() - .routeId(properties.getRouteId().toString()) - .serviceName(properties.getServiceName()) - // TODO: move to well known implementation key - .with("proxy", Boolean.FALSE.toString()).build(); - routingTable.register(tagsMetadata, rSocket); - }); - } - } - - private ConnectionSetupPayload getConnectionSetupPayload() { - DataBufferFactory dataBufferFactory = messageHandler.getRSocketStrategies() - .dataBufferFactory(); - NettyDataBufferFactory ndbf = (NettyDataBufferFactory) dataBufferFactory; - ByteBufAllocator byteBufAllocator = ndbf.getByteBufAllocator(); - Payload setupPayload = DefaultPayload.create(Unpooled.EMPTY_BUFFER, - Unpooled.EMPTY_BUFFER); - ByteBuf setup = SetupFrameFlyweight.encode(byteBufAllocator, false, 1, 1, - MESSAGE_RSOCKET_COMPOSITE_METADATA.getString(), - // TODO: configurable? - APPLICATION_CBOR.getString(), setupPayload); - return ConnectionSetupPayload.create(setup); - } - - @Override - public void stop() { - if (this.running.compareAndSet(true, false)) { - System.out.println(); - } - } - - @Override - public boolean isAutoStartup() { - return true; - } - - @Override - public void stop(Runnable callback) { - stop(); - if (callback != null) { - callback.run(); - } - } - - @Override - public int getPhase() { - return 0; - } - - @Override - public boolean isRunning() { - return this.running.get(); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerInfo.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerInfo.java deleted file mode 100644 index 972a9943..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerInfo.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.actuate; - -import java.math.BigInteger; -import java.util.Map; -import java.util.Objects; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata.Key; -import org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey; -import org.springframework.core.style.ToStringCreator; -import org.springframework.util.Assert; - -public final class BrokerInfo { - - private final BigInteger brokerId; - - private final long timestamp; - - private final Map tags; - - private BrokerInfo(BigInteger brokerId, long timestamp, Map tags) { - this.brokerId = brokerId; - this.timestamp = timestamp; - this.tags = tags; - } - - public BigInteger getBrokerId() { - return this.brokerId; - } - - public long getTimestamp() { - return this.timestamp; - } - - public Map getTags() { - return this.tags; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - BrokerInfo that = (BrokerInfo) o; - return this.timestamp == that.timestamp - && Objects.equals(this.brokerId, that.brokerId) - && Objects.equals(this.tags, that.tags); - } - - @Override - public int hashCode() { - return Objects.hash(this.brokerId, this.timestamp, this.tags); - } - - @Override - public String toString() { - // @formatter:off - return new ToStringCreator(this) - .append("id", brokerId) - .append("timestamp", timestamp) - .append("tags", getTags()) - .toString(); - // @formatter:on - } - - public static Builder of(BigInteger brokerId) { - return new Builder(brokerId); - } - - public static Builder of(Long brokerId) { - return of(BigInteger.valueOf(brokerId)); - } - - public static final class Builder { - - private final BigInteger brokerId; - - private long timestamp = System.currentTimeMillis(); - - private final TagsMetadata.Builder tagsBuilder = TagsMetadata.builder(); - - private Builder(BigInteger brokerId) { - Assert.notNull(brokerId, "brokerId may not be null"); - this.brokerId = brokerId; - } - - public Builder timestamp(long timestamp) { - this.timestamp = timestamp; - return this; - } - - public Builder with(String key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(WellKnownKey key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(Key key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(TagsMetadata tagsMetadata) { - tagsBuilder.with(tagsMetadata); - return this; - } - - public BrokerInfo build() { - Assert.isTrue(timestamp > 0, "timestamp must be > 0"); - return new BrokerInfo(brokerId, timestamp, tagsBuilder.build().getTags()); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/RouteJoin.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/RouteJoin.java deleted file mode 100644 index a1167f83..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/RouteJoin.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.actuate; - -import java.math.BigInteger; -import java.util.Map; -import java.util.Objects; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata.Key; -import org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey; -import org.springframework.core.style.ToStringCreator; -import org.springframework.util.Assert; - -public final class RouteJoin { - - private final BigInteger brokerId; - - private final BigInteger routeId; - - private final long timestamp; - - private final String serviceName; - - private final Map tags; - - public RouteJoin(BigInteger brokerId, BigInteger routeId, long timestamp, - String serviceName, Map tags) { - this.brokerId = brokerId; - this.routeId = routeId; - this.timestamp = timestamp; - this.serviceName = serviceName; - this.tags = tags; - } - - public BigInteger getBrokerId() { - return this.brokerId; - } - - public BigInteger getRouteId() { - return this.routeId; - } - - public long getTimestamp() { - return this.timestamp; - } - - public String getServiceName() { - return this.serviceName; - } - - public Map getTags() { - return this.tags; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - RouteJoin routeJoin = (RouteJoin) o; - return this.timestamp == routeJoin.timestamp - && Objects.equals(this.brokerId, routeJoin.brokerId) - && Objects.equals(this.routeId, routeJoin.routeId) - && Objects.equals(this.serviceName, routeJoin.serviceName) - && Objects.equals(this.tags, routeJoin.tags); - } - - @Override - public int hashCode() { - return Objects.hash(this.brokerId, this.routeId, this.timestamp, this.serviceName, - this.tags); - } - - @Override - public String toString() { - return new ToStringCreator(this).append("brokerId", brokerId) - .append("routeId", routeId).append("timestamp", timestamp) - .append("serviceName", serviceName).append("tags", tags).toString(); - - } - - public static Builder builder() { - return new Builder(); - } - - public static final class Builder { - - private BigInteger brokerId; - - private BigInteger routeId; - - private long timestamp = System.currentTimeMillis(); - - private String serviceName; - - private TagsMetadata.Builder tagsBuilder = TagsMetadata.builder(); - - public Builder brokerId(BigInteger brokerId) { - this.brokerId = brokerId; - return this; - } - - public Builder brokerId(long brokerId) { - return brokerId(BigInteger.valueOf(brokerId)); - } - - public Builder routeId(BigInteger routeId) { - this.routeId = routeId; - return this; - } - - public Builder routeId(long routeId) { - return routeId(BigInteger.valueOf(routeId)); - } - - public Builder timestamp(long timestamp) { - this.timestamp = timestamp; - return this; - } - - public Builder serviceName(String serviceName) { - this.serviceName = serviceName; - return this; - } - - public Builder with(String key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(WellKnownKey key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(Key key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(TagsMetadata tagsMetadata) { - tagsBuilder.with(tagsMetadata); - return this; - } - - public RouteJoin build() { - Assert.notNull(brokerId, "brokerId may not be null"); - Assert.notNull(routeId, "brokerId may not be null"); - Assert.notNull(serviceName, "brokerId may not be null"); - Assert.isTrue(timestamp > 0, "timestamp must be > 0"); - return new RouteJoin(brokerId, routeId, timestamp, serviceName, - tagsBuilder.build().getTags()); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/RouteRemove.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/RouteRemove.java deleted file mode 100644 index 817e3a44..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/actuate/RouteRemove.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.actuate; - -import java.math.BigInteger; -import java.util.Objects; - -import org.springframework.core.style.ToStringCreator; -import org.springframework.util.Assert; - -public final class RouteRemove { - - private final BigInteger brokerId; - - private final BigInteger routeId; - - private final long timestamp; - - public RouteRemove(BigInteger brokerId, BigInteger routeId, long timestamp) { - this.brokerId = brokerId; - this.routeId = routeId; - this.timestamp = timestamp; - } - - public BigInteger getBrokerId() { - return this.brokerId; - } - - public BigInteger getRouteId() { - return this.routeId; - } - - public long getTimestamp() { - return this.timestamp; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - RouteRemove routeJoin = (RouteRemove) o; - return this.timestamp == routeJoin.timestamp - && Objects.equals(this.brokerId, routeJoin.brokerId) - && Objects.equals(this.routeId, routeJoin.routeId); - } - - @Override - public int hashCode() { - return Objects.hash(this.brokerId, this.routeId, this.timestamp); - } - - @Override - public String toString() { - return new ToStringCreator(this).append("brokerId", brokerId) - .append("routeId", routeId).append("timestamp", timestamp).toString(); - - } - - public static Builder builder() { - return new Builder(); - } - - public static final class Builder { - - private BigInteger brokerId; - - private BigInteger routeId; - - private long timestamp = System.currentTimeMillis(); - - public Builder brokerId(BigInteger brokerId) { - this.brokerId = brokerId; - return this; - } - - public Builder brokerId(long brokerId) { - return brokerId(BigInteger.valueOf(brokerId)); - } - - public Builder routeId(BigInteger routeId) { - this.routeId = routeId; - return this; - } - - public Builder routeId(long routeId) { - return routeId(BigInteger.valueOf(routeId)); - } - - public Builder timestamp(long timestamp) { - this.timestamp = timestamp; - return this; - } - - public RouteRemove build() { - Assert.notNull(brokerId, "brokerId may not be null"); - Assert.notNull(routeId, "brokerId may not be null"); - Assert.isTrue(timestamp > 0, "timestamp must be > 0"); - return new RouteRemove(brokerId, routeId, timestamp); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/BrokerProperties.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/BrokerProperties.java deleted file mode 100644 index 5bf3fe93..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/BrokerProperties.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.autoconfigure; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.gateway.rsocket.common.autoconfigure.Broker; -import org.springframework.core.style.ToStringCreator; - -@ConfigurationProperties("spring.cloud.gateway.rsocket") -public class BrokerProperties { - - /** - * Enable Gateway RSocket. - */ - private boolean enabled = true; - - private String id = "gateway"; // TODO: + UUID? - - private BigInteger routeId; - - private String serviceName = "gateway"; - - private List brokers = new ArrayList<>(); - - /** - * Tag names and values to be supplied to Micrometer Interceptor. - */ - private List micrometerTags = new ArrayList<>(); - - public BrokerProperties() { - micrometerTags.add("component"); - micrometerTags.add("gateway"); - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public String getId() { - return this.id; - } - - public void setId(String id) { - this.id = id; - } - - public List getMicrometerTags() { - return micrometerTags; - } - - public void setMicrometerTags(List micrometerTags) { - this.micrometerTags = micrometerTags; - } - - public BigInteger getRouteId() { - return this.routeId; - } - - public void setRouteId(BigInteger routeId) { - this.routeId = routeId; - } - - public String getServiceName() { - return this.serviceName; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public List getBrokers() { - return this.brokers; - } - - public void setBrokers(List brokers) { - this.brokers = brokers; - } - - @Override - public String toString() { - // @formatter:off - return new ToStringCreator(this) - .append("enabled", enabled) - .append("id", id) - .append("micrometerTags", micrometerTags) - .append("routeId", routeId) - .append("serviceName", serviceName) - .append("brokers", brokers) - .toString(); - // @formatter:on - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketAutoConfiguration.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketAutoConfiguration.java deleted file mode 100644 index eb315080..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketAutoConfiguration.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.autoconfigure; - -import java.math.BigInteger; -import java.util.List; -import java.util.function.Supplier; - -import io.micrometer.core.instrument.MeterRegistry; -import io.rsocket.RSocket; - -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.rsocket.context.RSocketServerBootstrap; -import org.springframework.boot.rsocket.server.RSocketServerFactory; -import org.springframework.cloud.gateway.rsocket.actuate.BrokerActuator; -import org.springframework.cloud.gateway.rsocket.actuate.BrokerActuatorHandlerRegistration; -import org.springframework.cloud.gateway.rsocket.cluster.ClusterJoinListener; -import org.springframework.cloud.gateway.rsocket.cluster.ClusterService; -import org.springframework.cloud.gateway.rsocket.cluster.RouteJoinListener; -import org.springframework.cloud.gateway.rsocket.common.autoconfigure.GatewayRSocketCommonAutoConfiguration; -import org.springframework.cloud.gateway.rsocket.core.GatewayRSocketFactory; -import org.springframework.cloud.gateway.rsocket.core.GatewayServerRSocketFactoryProcessor; -import org.springframework.cloud.gateway.rsocket.core.PendingRequestRSocketFactory; -import org.springframework.cloud.gateway.rsocket.route.Routes; -import org.springframework.cloud.gateway.rsocket.routing.LoadBalancerFactory; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTableRoutes; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTableSocketAcceptorFilter; -import org.springframework.cloud.gateway.rsocket.socketacceptor.GatewaySocketAcceptor; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorFilter; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorPredicate; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorPredicateFilter; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; -import org.springframework.messaging.rsocket.RSocketStrategies; -import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; - -import static org.springframework.cloud.gateway.rsocket.common.autoconfigure.GatewayRSocketCommonAutoConfiguration.ID_GENERATOR_BEAN_NAME; - -/** - * @author Spencer Gibb - */ -@Configuration -@ConditionalOnProperty(name = "spring.cloud.gateway.rsocket.enabled", - matchIfMissing = true) -@EnableConfigurationProperties -@ConditionalOnClass(RSocket.class) -@AutoConfigureBefore(RSocketServerAutoConfiguration.class) -@AutoConfigureAfter(GatewayRSocketCommonAutoConfiguration.class) -public class GatewayRSocketAutoConfiguration { - - @Bean - public RoutingTable routingTable() { - return new RoutingTable(); - } - - // TODO: CompositeRoutes - @Bean - public RoutingTableRoutes registryRoutes(RoutingTable routingTable) { - return new RoutingTableRoutes(routingTable); - } - - @Bean - public RoutingTableSocketAcceptorFilter registrySocketAcceptorFilter( - RoutingTable routingTable) { - return new RoutingTableSocketAcceptorFilter(routingTable); - } - - @Bean - public PendingRequestRSocketFactory pendingRequestRSocketFactory( - RoutingTable routingTable, Routes routes, - RSocketStrategies rSocketStrategies) { - return new PendingRequestRSocketFactory(routingTable, routes, - rSocketStrategies.metadataExtractor()); - } - - @Bean - public LoadBalancerFactory loadBalancerFactory(RoutingTable routingTable) { - return new LoadBalancerFactory(routingTable); - } - - @Bean - public GatewayRSocketFactory gatewayRSocketFactory(RoutingTable routingTable, - Routes routes, PendingRequestRSocketFactory pendingFactory, - LoadBalancerFactory loadBalancerFactory, MeterRegistry meterRegistry, - BrokerProperties properties, RSocketStrategies rSocketStrategies) { - return new GatewayRSocketFactory(routingTable, routes, pendingFactory, - loadBalancerFactory, meterRegistry, properties, - rSocketStrategies.metadataExtractor()); - } - - @Bean - public BrokerProperties brokerProperties(Environment env, - @Qualifier(ID_GENERATOR_BEAN_NAME) Supplier idGenerator) { - BrokerProperties properties = new BrokerProperties(); - // set default from env - if (env.containsProperty("spring.application.name")) { - properties.setId(env.getProperty("spring.application.name")); - } - properties.setRouteId(idGenerator.get()); - return properties; - } - - @Bean - public SocketAcceptorPredicateFilter socketAcceptorPredicateFilter( - List predicates) { - return new SocketAcceptorPredicateFilter(predicates); - } - - @Bean - public GatewaySocketAcceptor socketAcceptor(GatewayRSocketFactory rsocketFactory, - List filters, MeterRegistry meterRegistry, - BrokerProperties properties, RSocketStrategies rSocketStrategies) { - return new GatewaySocketAcceptor(rsocketFactory, filters, meterRegistry, - properties, rSocketStrategies.metadataExtractor()); - } - - @Bean - public GatewayServerRSocketFactoryProcessor gatewayServerRSocketFactoryProcessor( - BrokerProperties properties, MeterRegistry meterRegistry) { - return new GatewayServerRSocketFactoryProcessor(properties, meterRegistry); - } - - @Bean - public RSocketServerBootstrap gatewayRSocketServerBootstrap( - RSocketServerFactory rSocketServerFactory, - GatewaySocketAcceptor gatewaySocketAcceptor) { - return new RSocketServerBootstrap(rSocketServerFactory, gatewaySocketAcceptor); - } - - @Bean - @ConditionalOnProperty(value = "spring.cloud.gateway.rsocket.broker.actuator.enabled", - matchIfMissing = true) - public BrokerActuatorHandlerRegistration brokerActuatorHandlerRegistration( - RoutingTable routingTable, RSocketMessageHandler messageHandler, - BrokerProperties properties) { - return new BrokerActuatorHandlerRegistration(routingTable, messageHandler, - properties); - } - - @Bean - @ConditionalOnProperty(value = "spring.cloud.gateway.rsocket.broker.actuator.enabled", - matchIfMissing = true) - public BrokerActuator brokerActuator(BrokerProperties properties, - ClusterService clusterService, RoutingTable routingTable) { - return new BrokerActuator(properties, clusterService, routingTable); - } - - @Configuration - @ConditionalOnProperty(name = "spring.cloud.gateway.rsocket.cluster.enabled", - matchIfMissing = true) - protected static class ClusterConfiguration { - - @Bean - public ClusterService clusterService() { - return new ClusterService(); - } - - @Bean - public ClusterJoinListener clusterJoinListener(ClusterService clusterService, - BrokerProperties properties, RSocketStrategies strategies, - GatewayRSocketFactory gatewayRSocketFactory) { - return new ClusterJoinListener(clusterService, properties, strategies, - gatewayRSocketFactory); - } - - @Bean - public RouteJoinListener routeJoinListener(ClusterService clusterService, - RoutingTable routingTable, BrokerProperties properties) { - return new RouteJoinListener(clusterService, routingTable, properties); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketEnvironmentPostProcessor.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketEnvironmentPostProcessor.java deleted file mode 100644 index 12f93f57..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketEnvironmentPostProcessor.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.autoconfigure; - -import java.util.Collections; -import java.util.Map; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.env.EnvironmentPostProcessor; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.MapPropertySource; - -public class GatewayRSocketEnvironmentPostProcessor implements EnvironmentPostProcessor { - - @Override - public void postProcessEnvironment(ConfigurableEnvironment env, - SpringApplication application) { - Boolean enabled = env.getProperty("spring.cloud.gateway.rsocket.enabled", - Boolean.class, true); - if (enabled && !env.containsProperty("spring.rsocket.server.port")) { - Map map = Collections - .singletonMap("spring.rsocket.server.port", 7002); - env.getPropertySources() - .addLast(new MapPropertySource("Default Gateway RSocket Port", map)); - } - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterJoinListener.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterJoinListener.java deleted file mode 100644 index d5cdb6d5..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterJoinListener.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.cluster; - -import java.math.BigInteger; - -import io.rsocket.SocketAcceptor; -import reactor.core.publisher.Mono; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; - -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.cloud.gateway.rsocket.actuate.BrokerActuator; -import org.springframework.cloud.gateway.rsocket.actuate.BrokerInfo; -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.common.autoconfigure.Broker; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.core.GatewayRSocketFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.messaging.rsocket.RSocketStrategies; - -public class ClusterJoinListener implements ApplicationListener { - - private final ClusterService clusterService; - - private final BrokerProperties properties; - - private final RSocketStrategies strategies; - - private final GatewayRSocketFactory gatewayRSocketFactory; - - public ClusterJoinListener(ClusterService clusterService, BrokerProperties properties, - RSocketStrategies strategies, GatewayRSocketFactory gatewayRSocketFactory) { - this.clusterService = clusterService; - this.properties = properties; - this.strategies = strategies; - this.gatewayRSocketFactory = gatewayRSocketFactory; - } - - @Override - public void onApplicationEvent(ApplicationReadyEvent event) { - for (Broker broker : properties.getBrokers()) { - RouteSetup routeSetup = RouteSetup - .of(properties.getRouteId(), properties.getServiceName()).build(); - - // TODO: micrometer - RSocketRequester.builder().rsocketStrategies(strategies) - .setupMetadata(routeSetup, RouteSetup.ROUTE_SETUP_MIME_TYPE) - .rsocketFactory(rsocketFactory -> rsocketFactory - .acceptor(brokerSocketAcceptor())) - // TODO: other types - .connectTcp(broker.getHost(), broker.getPort()) - .flatMap(this::callBrokerInfo).subscribe(this::registerOutgoing); - } - } - - /** - * For incoming requests to this broker node, the RSocketRequester needs an acceptor - * that is able to hand out GatewayRSocket instances. So here is a very simple one - * that just constructs tags metadata and creates a GatewayRSocket. - * @return A SocketAcceptor that creates a GatewayRSocket. - */ - SocketAcceptor brokerSocketAcceptor() { - return (setup, sendingSocket) -> { - TagsMetadata.Builder builder = TagsMetadata.builder(); - // TODO: other tags. - builder.serviceName(properties.getServiceName()) - .routeId(properties.getRouteId().toString()); - return Mono.just(gatewayRSocketFactory.create(builder.build())); - }; - } - - Mono> callBrokerInfo( - RSocketRequester requester) { - Forwarding forwarding = Forwarding.of(properties.getRouteId()) - .serviceName("gateway").disableProxy().build(); - return requester.route(BrokerActuator.BROKER_INFO_PATH) - .metadata(forwarding, Forwarding.FORWARDING_MIME_TYPE) - .data(BrokerInfo.of(properties.getRouteId()).build()) - .retrieveMono(BigInteger.class) - .map(brokerId -> Tuples.of(brokerId, requester)); - } - - boolean registerOutgoing(Tuple2 tuple) { - return clusterService.registerOutgoing(tuple.getT1().toString(), tuple.getT2()); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterService.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterService.java deleted file mode 100644 index a9c090c5..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterService.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.cluster; - -import java.math.BigInteger; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.cloud.gateway.rsocket.actuate.BrokerActuator; -import org.springframework.cloud.gateway.rsocket.actuate.BrokerInfo; -import org.springframework.cloud.gateway.rsocket.actuate.RouteJoin; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.core.style.ToStringCreator; -import org.springframework.messaging.rsocket.RSocketRequester; - -public class ClusterService { - - final Map incomingBrokers = new ConcurrentHashMap<>(); - - final Map outgoingBrokers = new ConcurrentHashMap<>(); - - public boolean registerIncoming(BrokerInfo brokerInfo) { - String brokerId = brokerInfo.getBrokerId().toString(); - - // TODO: validate that there is a corresponding route in RoutingTable - if (incomingBrokers.containsKey(brokerId)) { - BrokerEntry brokerEntry = incomingBrokers.get(brokerId); - if (brokerEntry.timestamp < brokerInfo.getTimestamp()) { - incomingBrokers.put(brokerId, new BrokerEntry(brokerInfo.getBrokerId(), - brokerInfo.getTags(), brokerInfo.getTimestamp())); - return true; - } - } - else { - incomingBrokers.put(brokerId, new BrokerEntry(brokerInfo.getBrokerId(), - brokerInfo.getTags(), brokerInfo.getTimestamp())); - return true; - } - return false; - } - - public boolean registerOutgoing(String routeId, RSocketRequester requester) { - // TODO: BrokerClient instead of RSocketRequester? - // TODO: validation - outgoingBrokers.put(routeId, requester); - return true; - } - - public boolean send(RouteJoin routeJoin) { - outgoingBrokers.values().forEach(requester -> { - Forwarding forwarding = Forwarding.of(routeJoin.getRouteId()) - .serviceName("gateway").disableProxy().build(); - requester.route(BrokerActuator.ROUTE_JOIN_PATH) - .metadata(forwarding, Forwarding.FORWARDING_MIME_TYPE).data(routeJoin) - .retrieveMono(RouteJoin.class) - .subscribe(res -> System.out.println("RouteJoin: " + res)); - }); - return true; - } - - static class BrokerEntry { - - private final BigInteger brokerId; - - private final Map tags; - - private final Long timestamp; - - BrokerEntry(BigInteger brokerId, Map tags, - Long timestamp) { - this.brokerId = brokerId; - this.tags = tags; - this.timestamp = timestamp; - } - - public BigInteger getBrokerId() { - return this.brokerId; - } - - public Map getTags() { - return this.tags; - } - - public Long getTimestamp() { - return this.timestamp; - } - - @Override - public String toString() { - // @formatter:off - return new ToStringCreator(this) - .append("brokerId", brokerId) - .append("tags", tags) - .append("timestamp", timestamp) - .toString(); - // @formatter:on - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/RouteJoinListener.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/RouteJoinListener.java deleted file mode 100644 index 70f22389..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/cluster/RouteJoinListener.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.cluster; - -import java.math.BigInteger; -import java.util.function.Consumer; - -import org.springframework.cloud.gateway.rsocket.actuate.RouteJoin; -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable.RegisteredEvent; - -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.SERVICE_NAME; - -public class RouteJoinListener implements Consumer { - - private final ClusterService clusterService; - - private final RoutingTable routingTable; - - private final BrokerProperties properties; - - public RouteJoinListener(ClusterService clusterService, RoutingTable routingTable, - BrokerProperties properties) { - this.clusterService = clusterService; - this.routingTable = routingTable; - this.properties = properties; - routingTable.addListener(this); - } - - @Override - public void accept(RegisteredEvent registeredEvent) { - BigInteger brokerId = properties.getRouteId(); - TagsMetadata tagsMetadata = registeredEvent.getRoutingMetadata(); - String serviceName = tagsMetadata.get(SERVICE_NAME); - - // Do not send RouteJoin requests for self - if (!brokerId.toString().equals(tagsMetadata.getRouteId()) && - // or for other gateways yet - !"gateway".equals(serviceName)) { - BigInteger routeId = new BigInteger(tagsMetadata.getRouteId()); - RouteJoin routeJoin = RouteJoin.builder().brokerId(brokerId).routeId(routeId) - .serviceName(serviceName).with(tagsMetadata).build(); - - clusterService.send(routeJoin); - } - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/AbstractGatewayRSocket.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/AbstractGatewayRSocket.java deleted file mode 100644 index 96a7976d..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/AbstractGatewayRSocket.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tags; -import io.rsocket.AbstractRSocket; -import io.rsocket.Payload; -import io.rsocket.ResponderRSocket; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.messaging.rsocket.MetadataExtractor; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Convience class to hold and calculate exchange and metrics related information. - */ -public abstract class AbstractGatewayRSocket extends AbstractRSocket - implements ResponderRSocket { - - private static final Log log = LogFactory.getLog(AbstractGatewayRSocket.class); - - protected final MeterRegistry meterRegistry; - - private final BrokerProperties properties; - - private final MetadataExtractor metadataExtractor; - - private final TagsMetadata metadata; - - AbstractGatewayRSocket(MeterRegistry meterRegistry, BrokerProperties properties, - MetadataExtractor metadataExtractor, TagsMetadata metadata) { - this.meterRegistry = meterRegistry; - this.properties = properties; - this.metadataExtractor = metadataExtractor; - this.metadata = metadata; - } - - protected GatewayExchange createExchange(GatewayExchange.Type type, Payload payload) { - GatewayExchange exchange = GatewayExchange.fromPayload(type, payload, - metadataExtractor); - Tags tags = getTags(exchange); - exchange.setTags(tags); - return exchange; - } - - protected Tags getTags(GatewayExchange exchange) { - // TODO: add tags to exchange - String requesterName = "FIXME"; // FIXME: this.metadata.get(SERVICE_NAME); - String requesterId = "FIXME"; // FIXME: this.metadata.getRouteId(); - String responderName = "FIXME"; // FIXME: exchange.getRoutingMetadata().getName(); - Assert.hasText(responderName, "responderName must not be empty"); - Assert.hasText(requesterId, "requesterId must not be empty"); - Assert.hasText(requesterName, "requesterName must not be empty"); - // responder.id happens in a callback, later - return Tags.of("requester.name", requesterName, "responder.name", responderName, - "requester.id", requesterId, "gateway.id", this.properties.getId()); - } - - protected void count(GatewayExchange exchange, String suffix) { - count(exchange, suffix, Tags.empty()); - } - - protected void count(GatewayExchange exchange, Tags additionalTags) { - count(exchange, null, additionalTags); - } - - protected void count(GatewayExchange exchange, String suffix, Tags additionalTags) { - Tags tags = exchange.getTags().and(additionalTags); - String name = getMetricName(exchange, suffix); - this.meterRegistry.counter(name, tags).increment(); - } - - protected String getMetricName(GatewayExchange exchange) { - return getMetricName(exchange, null); - } - - protected String getMetricName(GatewayExchange exchange, String suffix) { - StringBuilder name = new StringBuilder("forward."); - name.append(exchange.getType().getKey()); - if (StringUtils.hasLength(suffix)) { - name.append("."); - name.append(suffix); - } - return name.toString(); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayExchange.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayExchange.java deleted file mode 100644 index b552d8a7..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayExchange.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import java.util.Map; - -import io.micrometer.core.instrument.Tags; -import io.rsocket.Payload; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.Metadata; -import org.springframework.cloud.gateway.rsocket.filter.AbstractRSocketExchange; -import org.springframework.messaging.rsocket.MetadataExtractor; - -/** - * Exchange object used in GatewayFilterChain started by GatewayRSocket. - */ -public class GatewayExchange extends AbstractRSocketExchange { - - private static final Log log = LogFactory.getLog(GatewayExchange.class); - - /** - * Key for the route object in attributes. - */ - public static final String ROUTE_ATTR = "__route_attr_"; - - public enum Type { - - /** - * RSocket fire and forget request type. - */ - FIRE_AND_FORGET("request.fnf"), - - /** - * RSocket request channel request type. - */ - REQUEST_CHANNEL("request.channel"), - - /** - * RSocket request response request type. - */ - REQUEST_RESPONSE("request.response"), - - /** - * RSocket request stream request type. - */ - REQUEST_STREAM("request.stream"); - - private String key; - - Type(String key) { - this.key = key; - } - - String getKey() { - return this.key; - } - - } - - private final Type type; - - private final Forwarding routingMetadata; - - private Tags tags = Tags.empty(); - - public static GatewayExchange fromPayload(Type type, Payload payload, - MetadataExtractor metadataExtractor) { - if (payload == null || !payload.hasMetadata()) { - return null; - } - - // TODO: deal with payload mimetype - Map metadataMap = metadataExtractor.extract(payload, - Metadata.COMPOSITE_MIME_TYPE); - - GatewayExchange exchange = new GatewayExchange(type, - getForwardingMetadata(metadataMap)); - - // TODO: custm metadata extractors - // Adds routing metadata to exchange - if (metadataMap.containsKey("route")) { - exchange.getAttributes().put("route-metadata", metadataMap.get("route")); - } - - return exchange; - } - - private static Forwarding getForwardingMetadata(Map metadataMap) { - if (metadataMap.containsKey("forwarding")) { - Forwarding metadata = (Forwarding) metadataMap.get("forwarding"); - - if (log.isDebugEnabled()) { - log.debug("found routing metadata " + metadata); - } - return metadata; - } - - return null; - } - - public GatewayExchange(Type type, Forwarding routingMetadata) { - this.type = type; - this.routingMetadata = routingMetadata; - } - - public Type getType() { - return type; - } - - public Forwarding getRoutingMetadata() { - return routingMetadata; - } - - public Tags getTags() { - return this.tags; - } - - public void setTags(Tags tags) { - this.tags = tags; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayFilter.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayFilter.java deleted file mode 100644 index 7fb2f848..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayFilter.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import org.springframework.cloud.gateway.rsocket.filter.RSocketFilter; - -public interface GatewayFilter - extends RSocketFilter { - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayFilterChain.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayFilterChain.java deleted file mode 100644 index 7fdad76b..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayFilterChain.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import java.util.List; - -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.filter.AbstractFilterChain; -import org.springframework.cloud.gateway.rsocket.filter.RSocketFilter.Success; - -public class GatewayFilterChain - extends AbstractFilterChain { - - /** - * Public constructor with the list of filters and the target handler to use. - * @param filters the filters ahead of the handler - */ - private GatewayFilterChain(List filters) { - super(filters); - } - - protected GatewayFilterChain(List allFilters, - GatewayFilter currentFilter, GatewayFilterChain next) { - super(allFilters, currentFilter, next); - } - - @Override - protected GatewayFilterChain create(List allFilters, - GatewayFilter currentFilter, GatewayFilterChain next) { - return new GatewayFilterChain(allFilters, currentFilter, next); - } - - public static Mono executeFilterChain(List filters, - GatewayExchange exchange) { - return new GatewayFilterChain(filters).filter(exchange); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayPredicate.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayPredicate.java deleted file mode 100644 index a01a4944..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayPredicate.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import org.springframework.cloud.gateway.rsocket.support.AsyncPredicate; - -public interface GatewayPredicate extends AsyncPredicate { - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocket.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocket.java deleted file mode 100644 index 1069e5d9..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocket.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; -import java.util.logging.Level; -import java.util.stream.Collectors; - -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tags; -import io.micrometer.core.instrument.Timer; -import io.rsocket.Payload; -import io.rsocket.RSocket; -import io.rsocket.ResponderRSocket; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.util.function.Tuple2; - -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata.Key; -import org.springframework.cloud.gateway.rsocket.route.Route; -import org.springframework.cloud.gateway.rsocket.route.Routes; -import org.springframework.cloud.gateway.rsocket.routing.LoadBalancerFactory; -import org.springframework.messaging.rsocket.MetadataExtractor; - -import static org.springframework.cloud.gateway.rsocket.core.GatewayExchange.ROUTE_ATTR; -import static org.springframework.cloud.gateway.rsocket.core.GatewayExchange.Type.FIRE_AND_FORGET; -import static org.springframework.cloud.gateway.rsocket.core.GatewayExchange.Type.REQUEST_CHANNEL; -import static org.springframework.cloud.gateway.rsocket.core.GatewayExchange.Type.REQUEST_RESPONSE; -import static org.springframework.cloud.gateway.rsocket.core.GatewayExchange.Type.REQUEST_STREAM; -import static org.springframework.cloud.gateway.rsocket.core.GatewayFilterChain.executeFilterChain; - -/** - * Acts as a proxy to other registered sockets. Creates a GatewayExchange and attempts to - * locate a Route. If a Route is found, it is added to the exchange and the filter chains - * is executed againts the Route's filters. If the filter chain is successful, an attempt - * to locate a target RSocket via the Registry is executed. If not found a pending RSocket - * is returned. - */ -public class GatewayRSocket extends AbstractGatewayRSocket { - - private static final Log log = LogFactory.getLog(GatewayRSocket.class); - - private final Routes routes; - - private final PendingRequestRSocketFactory pendingFactory; - - private final LoadBalancerFactory loadBalancerFactory; - - GatewayRSocket(Routes routes, PendingRequestRSocketFactory pendingFactory, - LoadBalancerFactory loadBalancerFactory, MeterRegistry meterRegistry, - BrokerProperties properties, MetadataExtractor metadataExtractor, - TagsMetadata metadata) { - super(meterRegistry, properties, metadataExtractor, metadata); - this.routes = routes; - this.pendingFactory = pendingFactory; - this.loadBalancerFactory = loadBalancerFactory; - } - - protected PendingRequestRSocketFactory getPendingFactory() { - return this.pendingFactory; - } - - @Override - public Mono fireAndForget(Payload payload) { - GatewayExchange exchange = createExchange(FIRE_AND_FORGET, payload); - return findRSocketOrCreatePending(exchange).flatMap(rSockets -> { - retain(payload, rSockets); - List> results = rSockets.stream() - .map(rSocket -> rSocket.fireAndForget(payload)) - .collect(Collectors.toList()); - // TODO: this looks weird - return Flux.merge(results).then(); - }).doOnError(t -> count(exchange, "error")).doFinally(s -> count(exchange, "")); - } - - @Override - public Flux requestChannel(Payload payload, Publisher payloads) { - GatewayExchange exchange = createExchange(REQUEST_CHANNEL, payload); - Tags responderTags = Tags.of("source", "responder"); - return findRSocketOrCreatePending(exchange).flatMapMany(rSockets -> { - Tags requesterTags = Tags.of("source", "requester"); - Flux flux = Flux.from(payloads).doOnNext(p -> { - retain(p, rSockets); - count(exchange, "payload", requesterTags); - }).doOnError(t -> count(exchange, "error", requesterTags)) - .doFinally(s -> count(exchange, requesterTags)).publish() - .refCount(rSockets.size()); - - List> payloadList = rSockets.stream().map(rSocket -> { - if (rSocket instanceof ResponderRSocket) { - ResponderRSocket socket = (ResponderRSocket) rSocket; - return socket.requestChannel(payload, flux); - } - else { - return rSocket.requestChannel(flux); - } - }).collect(Collectors.toList()); - - return Flux.merge(payloadList).log( - GatewayRSocket.class.getName() + ".request-channel", Level.FINEST); - }).doOnNext(s -> count(exchange, "payload", responderTags)) - .doOnError(t -> count(exchange, "error", responderTags)) - .doFinally(s -> count(exchange, responderTags)); - } - - @Override - public Mono requestResponse(Payload payload) { - AtomicReference timer = new AtomicReference<>(); - GatewayExchange exchange = createExchange(REQUEST_RESPONSE, payload); - return findRSocketOrCreatePending(exchange).flatMap(rSockets -> { - retain(payload, rSockets); - List> results = rSockets.stream() - .map(rSocket -> rSocket.requestResponse(payload)) - .collect(Collectors.toList()); - - return Flux.merge(results).next(); - // TODO: does this cancel the others? - }).doOnSubscribe(s -> timer.set(Timer.start(meterRegistry))) - .doOnError(t -> count(exchange, "error")) - .doFinally(s -> timer.get().stop(meterRegistry - .timer(getMetricName(exchange), exchange.getTags()))); - } - - @Override - public Flux requestStream(Payload payload) { - GatewayExchange exchange = createExchange(REQUEST_STREAM, payload); - return findRSocketOrCreatePending(exchange).flatMapMany(rSockets -> { - retain(payload, rSockets); - List> results = rSockets.stream() - .map(rSocket -> rSocket.requestStream(payload)) - .collect(Collectors.toList()); - return Flux.merge(results); - }) - // S N E F - .doOnNext(s -> count(exchange, "payload")) - .doOnError(t -> count(exchange, "error")) - .doFinally(s -> count(exchange, Tags.empty())); - } - - private void retain(Payload payload, List rSockets) { - if (rSockets.size() > 1) { - payload.retain(rSockets.size() - 1); - } - } - - /** - * First locate Route. If found, put route in exchange and execute filter chain. If - * successful, locate target RSocket. If not found, create a pending RSocket. - * @param exchange GatewayExchange. - * @return Target RSocket or empty. - */ - private Mono> findRSocketOrCreatePending(GatewayExchange exchange) { - return this.routes.findRoute(exchange) - .log(GatewayRSocket.class.getName() + ".find route", Level.FINEST) - .flatMap(route -> { - // put route in exchange for later use - exchange.getAttributes().put(ROUTE_ATTR, route); - return findRSocketOrCreatePending(exchange, route); - }).switchIfEmpty(createPending(exchange)); - - // TODO: deal with connecting to cluster? - } - - private Mono> findRSocketOrCreatePending(GatewayExchange exchange, - Route route) { - return executeFilterChain(route.getFilters(), exchange) - .log(GatewayRSocket.class.getName() + ".after filter chain", Level.FINEST) - .flatMapMany(success -> { - Map tags = exchange.getRoutingMetadata().getTags(); - // TODO: use frame flag - if (tags.containsKey(new Key("multicast"))) { - List> rsockets = loadBalancerFactory - .find(exchange.getRoutingMetadata()); - return Flux.fromIterable(rsockets); - } - return loadBalancerFactory.choose(exchange.getRoutingMetadata()) - .flatMapMany( - tuple -> Flux.just((Tuple2) tuple)); - }).map(tuple -> { - // TODO: this is routeId, should it be service name? - // Tags tags = exchange.getTags().and("responder.id", tuple.getT1()); - // exchange.setTags(tags); - return tuple.getT2(); - }).cast(RSocket.class).map(rSocket -> { - if (log.isDebugEnabled()) { - log.debug("Found RSocket: " + rSocket); - } - return rSocket; - }).collectList() - .log(GatewayRSocket.class.getName() + ".find rsocket", Level.FINEST); - } - - protected Mono> createPending(GatewayExchange exchange) { - if (log.isDebugEnabled()) { - log.debug("Unable to find destination RSocket for " - + exchange.getRoutingMetadata()); - } - // if a route can't be found or registered RSocket, create pending - return pendingFactory.create(exchange).cast(RSocket.class) - .map(Collections::singletonList); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketFactory.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketFactory.java deleted file mode 100644 index 62da6bc2..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketFactory.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import io.micrometer.core.instrument.MeterRegistry; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.route.Routes; -import org.springframework.cloud.gateway.rsocket.routing.LoadBalancerFactory; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable; -import org.springframework.messaging.rsocket.MetadataExtractor; -import org.springframework.util.Assert; - -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.ROUTE_ID; -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.SERVICE_NAME; - -public class GatewayRSocketFactory { - - private static final Log log = LogFactory.getLog(GatewayRSocket.class); - - private final RoutingTable routingTable; - - private final Routes routes; - - private final PendingRequestRSocketFactory pendingFactory; - - private final LoadBalancerFactory loadBalancerFactory; - - private final MeterRegistry meterRegistry; - - private final BrokerProperties properties; - - private final MetadataExtractor metadataExtractor; - - public GatewayRSocketFactory(RoutingTable routingTable, Routes routes, - PendingRequestRSocketFactory pendingFactory, - LoadBalancerFactory loadBalancerFactory, MeterRegistry meterRegistry, - BrokerProperties properties, MetadataExtractor metadataExtractor) { - this.routingTable = routingTable; - this.routes = routes; - this.pendingFactory = pendingFactory; - this.loadBalancerFactory = loadBalancerFactory; - this.meterRegistry = meterRegistry; - this.properties = properties; - this.metadataExtractor = metadataExtractor; - } - - @SuppressWarnings("Duplicates") - public GatewayRSocket create(TagsMetadata metadata) { - Assert.hasText(metadata.get(ROUTE_ID), "metadata must contain " + ROUTE_ID); - Assert.hasText(metadata.get(SERVICE_NAME), - "metadata must contain " + SERVICE_NAME); - - GatewayRSocket gatewayRSocket = new GatewayRSocket(this.routes, - this.pendingFactory, this.loadBalancerFactory, this.meterRegistry, - this.properties, this.metadataExtractor, metadata); - gatewayRSocket.onClose().doOnSuccess(v -> { - if (log.isDebugEnabled()) { - log.debug("Closed, deregistering " + metadata); - } - routingTable.deregister(metadata); - }).doOnError(t -> { - if (log.isErrorEnabled()) { - log.error("Error received, deregistering " + metadata, t); - } - routingTable.deregister(metadata); - }).doOnNext(v -> { - if (log.isTraceEnabled()) { - log.trace("OnClose doOnNext"); - } - }).doOnTerminate(() -> { - if (log.isTraceEnabled()) { - log.trace("OnClose doOnTerminate"); - } - }).doFinally(st -> { - if (log.isTraceEnabled()) { - log.trace("OnClose doFinally"); - } - }).subscribe(); - return gatewayRSocket; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayServerRSocketFactoryProcessor.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayServerRSocketFactoryProcessor.java deleted file mode 100644 index f145cc31..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/GatewayServerRSocketFactoryProcessor.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tag; -import io.micrometer.core.instrument.Tags; -import io.rsocket.RSocketFactory.ServerRSocketFactory; -import io.rsocket.micrometer.MicrometerDuplexConnectionInterceptor; -import io.rsocket.plugins.RSocketInterceptor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.rsocket.server.ServerRSocketFactoryProcessor; -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.util.Assert; - -public class GatewayServerRSocketFactoryProcessor - implements ServerRSocketFactoryProcessor { - - private static final Log log = LogFactory - .getLog(GatewayServerRSocketFactoryProcessor.class); - - private static final RSocketInterceptor[] EMPTY_INTERCEPTORS = new RSocketInterceptor[0]; - - private final BrokerProperties properties; - - private final List serverInterceptors; - - private final MeterRegistry meterRegistry; - - public GatewayServerRSocketFactoryProcessor(BrokerProperties properties, - MeterRegistry meterRegistry) { - this(properties, meterRegistry, EMPTY_INTERCEPTORS); - } - - public GatewayServerRSocketFactoryProcessor(BrokerProperties properties, - MeterRegistry meterRegistry, RSocketInterceptor... interceptors) { - Assert.notNull(properties, "properties may not be null"); - Assert.notNull(meterRegistry, "meterRegistry may not be null"); - Assert.notNull(interceptors, "interceptors may not be null"); - this.properties = properties; - this.meterRegistry = meterRegistry; - this.serverInterceptors = Arrays.asList(interceptors); - } - - @Override - public ServerRSocketFactory process(ServerRSocketFactory factory) { - serverInterceptors.forEach(factory::addResponderPlugin); - - List micrometerTags = properties.getMicrometerTags(); - Tag[] tags = Tags.of(micrometerTags.toArray(new String[] {})) - .and("gateway.id", properties.getId()).stream() - .collect(Collectors.toList()).toArray(new Tag[] {}); - - return factory - // TODO: add as bean like serverInterceptors above - .addConnectionPlugin( - new MicrometerDuplexConnectionInterceptor(meterRegistry, tags)) - .errorConsumer(throwable -> { - if (log.isDebugEnabled()) { - log.debug("Error with connection", throwable); - } - }); // TODO: add configurable errorConsumer - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/PendingRequestRSocket.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/PendingRequestRSocket.java deleted file mode 100644 index 0cf7183a..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/PendingRequestRSocket.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.logging.Level; - -import io.rsocket.AbstractRSocket; -import io.rsocket.Payload; -import io.rsocket.RSocket; -import io.rsocket.ResponderRSocket; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import reactor.core.Disposable; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.core.publisher.MonoProcessor; -import reactor.util.function.Tuple2; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.filter.RSocketFilter.Success; -import org.springframework.cloud.gateway.rsocket.route.Route; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable.RegisteredEvent; -import org.springframework.messaging.rsocket.MetadataExtractor; - -import static org.springframework.cloud.gateway.rsocket.core.GatewayExchange.ROUTE_ATTR; -import static org.springframework.cloud.gateway.rsocket.core.GatewayExchange.Type.REQUEST_STREAM; -import static org.springframework.cloud.gateway.rsocket.core.GatewayFilterChain.executeFilterChain; - -public class PendingRequestRSocket extends AbstractRSocket - implements ResponderRSocket, Consumer { - - private static final Log log = LogFactory.getLog(PendingRequestRSocket.class); - - // TODO: if this were just routeId & route wasn't an exchange attr would be simpler. - private final Function> routeFinder; - - private final MetadataExtractor metadataExtractor; - - private final Consumer metadataCallback; - - private final MonoProcessor rSocketProcessor; - - private Disposable subscriptionDisposable; - - private Route route; - - public PendingRequestRSocket(MetadataExtractor metadataExtractor, - Function> routeFinder, - Consumer metadataCallback) { - this(metadataExtractor, routeFinder, metadataCallback, MonoProcessor.create()); - } - - /* for testing */ PendingRequestRSocket(MetadataExtractor metadataExtractor, - Function> routeFinder, - Consumer metadataCallback, - MonoProcessor rSocketProcessor) { - this.routeFinder = routeFinder; - this.metadataExtractor = metadataExtractor; - this.metadataCallback = metadataCallback; - this.rSocketProcessor = rSocketProcessor; - } - - /** - * Find route (if needed) using pendingExchange. If found, see if the route target - * matches the registered service. If it matches, send registered RSocket to - * processor. Then execute normal filter chain. If filter chain is successful, execute - * request. - * @param registeredEvent the RegisteredEvent - */ - @Override - public void accept(RegisteredEvent registeredEvent) { - this.routeFinder.apply(registeredEvent).subscribe(route -> { - this.route = route; - this.metadataCallback.accept(registeredEvent.getRoutingMetadata()); - this.rSocketProcessor.onNext(registeredEvent.getRSocket()); - this.rSocketProcessor.onComplete(); - if (this.subscriptionDisposable != null) { - this.subscriptionDisposable.dispose(); - } - }); - } - - @Override - public Mono fireAndForget(Payload payload) { - return processor("pending-request-faf", payload) - .flatMap(tuple -> tuple.getT1().fireAndForget(payload)); - } - - @Override - public Mono requestResponse(Payload payload) { - return processor("pending-request-rr", payload) - .flatMap(tuple -> tuple.getT1().requestResponse(payload)); - } - - @Override - public Flux requestStream(Payload payload) { - return processor("pending-request-rs", payload) - .flatMapMany(tuple -> tuple.getT1().requestStream(payload)); - } - - @Override - public Flux requestChannel(Payload payload, Publisher payloads) { - return processor("pending-request-rc", payload).flatMapMany(tuple -> { - RSocket rSocket = tuple.getT1(); - if (rSocket instanceof ResponderRSocket) { - ResponderRSocket socket = (ResponderRSocket) rSocket; - return socket.requestChannel(payload, payloads); - } - return rSocket.requestChannel(payloads); - }); - } - - /** - * After processor receives onNext signal, get route from exchange attrs, create a new - * exchange from payload. Copy exchange attrs. Execute filter chain, if successful, - * execute request. - * @param logCategory log category - * @param payload payload. - * @return - */ - protected Mono> processor(String logCategory, - Payload payload) { - return rSocketProcessor - .log(PendingRequestRSocket.class.getName() + "." + logCategory, - Level.FINEST) - .flatMap(rSocket -> { - GatewayExchange exchange = GatewayExchange.fromPayload(REQUEST_STREAM, - payload, metadataExtractor); - exchange.getAttributes().put(ROUTE_ATTR, route); - // exchange.getAttributes().putAll(pendingExchange.getAttributes()); - return Mono.just(rSocket) - .zipWith(executeFilterChain(route.getFilters(), exchange)); - }); - - } - - public void setSubscriptionDisposable(Disposable subscriptionDisposable) { - this.subscriptionDisposable = subscriptionDisposable; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/PendingRequestRSocketFactory.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/PendingRequestRSocketFactory.java deleted file mode 100644 index 10e522c0..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/core/PendingRequestRSocketFactory.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import java.util.Set; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.logging.Level; - -import io.micrometer.core.instrument.Tags; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.Disposable; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.route.Route; -import org.springframework.cloud.gateway.rsocket.route.Routes; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable; -import org.springframework.messaging.rsocket.MetadataExtractor; - -public class PendingRequestRSocketFactory { - - private static final Log log = LogFactory.getLog(PendingRequestRSocket.class); - - private final RoutingTable routingTable; - - private final Routes routes; - - private final MetadataExtractor metadataExtractor; - - public PendingRequestRSocketFactory(RoutingTable routingTable, Routes routes, - MetadataExtractor metadataExtractor) { - this.routingTable = routingTable; - this.routes = routes; - this.metadataExtractor = metadataExtractor; - } - - public Mono create(GatewayExchange exchange) { - if (log.isDebugEnabled()) { - log.debug("creating pending RSocket for " + exchange.getRoutingMetadata()); - } - PendingRequestRSocket pending = constructPendingRSocket(exchange); - Disposable disposable = this.routingTable.addListener(pending); - pending.setSubscriptionDisposable(disposable); - return Mono.just(pending); - } - - protected PendingRequestRSocket constructPendingRSocket(GatewayExchange exchange) { - Function> routeFinder = registeredEvent -> getRouteMono( - registeredEvent, exchange); - Consumer tagsMetadataConsumer = tagsMetadata -> { - Tags tags = exchange.getTags().and("responder.id", tagsMetadata.getRouteId()); - exchange.setTags(tags); - }; - return new PendingRequestRSocket(metadataExtractor, routeFinder, - tagsMetadataConsumer); - } - - /** - * Finds routes using exchange of original request that created pending RSocket. - * @param registeredEvent newly registered event - * @param exchange from original request - * @return route if route matches - */ - protected Mono getRouteMono(RoutingTable.RegisteredEvent registeredEvent, - GatewayExchange exchange) { - return this.routes.findRoute(exchange) - .log(PendingRequestRSocket.class.getName() + ".find route pending", - Level.FINEST) - // TODO: can this be replaced with filter? - .flatMap( - route -> matchRoute(route, registeredEvent.getRoutingMetadata())); - } - - /** - * Matches route found using original exchange with routeIds from recently registered - * routes. - * @param route route found using original exchange. - * @param tagsMetadata tags from recent registration. - * @return - */ - private Mono matchRoute(Route route, TagsMetadata tagsMetadata) { - Set routeIds = this.routingTable.findRouteIds(tagsMetadata); - if (routeIds.contains(route.getId())) { - return Mono.just(route); - } - return Mono.empty(); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/AbstractFilterChain.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/AbstractFilterChain.java deleted file mode 100644 index 024c6b92..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/AbstractFilterChain.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.filter; - -import java.util.Collections; -import java.util.List; -import java.util.ListIterator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.filter.RSocketFilter.Success; -import org.springframework.lang.Nullable; - -/** - * Default implementation of {@link FilterChain}. - * - *

- * Each instance of this class represents one link in the chain. The public constructor - * {@link #AbstractFilterChain(List)} initializes the full chain and represents its first - * link. - * - *

- * This class is immutable and thread-safe. It can be created once and re-used to handle - * request concurrently. - * - * Copied from org.springframework.web.server.handler.AbstractFilterChain - * - * @since 5.0 - */ -public abstract class AbstractFilterChain - implements FilterChain { - - private final Log log = LogFactory.getLog(getClass()); - - protected final List allFilters; - - @Nullable - protected final F currentFilter; - - @Nullable - protected final FC next; - - /** - * Public constructor with the list of filters and the target handler to use. - * @param filters the filters ahead of the handler - */ - @SuppressWarnings("unchecked") - protected AbstractFilterChain(List filters) { - this.allFilters = Collections.unmodifiableList(filters); - FC chain = initChain(filters); - this.currentFilter = (F) chain.currentFilter; - this.next = (FC) chain.next; - } - - private FC initChain(List filters) { - FC chain = create(filters, null, null); - ListIterator iterator = filters.listIterator(filters.size()); - while (iterator.hasPrevious()) { - chain = create(filters, iterator.previous(), chain); - } - return chain; - } - - /** - * Private constructor to represent one link in the chain. - */ - protected AbstractFilterChain(List allFilters, @Nullable F currentFilter, - @Nullable FC next) { - - this.allFilters = allFilters; - this.currentFilter = currentFilter; - this.next = next; - } - - /** - * Private constructor to represent one link in the chain. - */ - protected abstract FC create(List allFilters, @Nullable F currentFilter, - @Nullable FC next); - - public List getFilters() { - return this.allFilters; - } - - @Override - @SuppressWarnings("unchecked") - public Mono filter(E exchange) { - return Mono.defer(() -> this.currentFilter != null && this.next != null - ? this.currentFilter.filter(exchange, this.next) : getMonoSuccess()); - } - - private Mono getMonoSuccess() { - if (log.isDebugEnabled()) { - log.debug("filter chain completed with success"); - } - return MONO_SUCCESS; - } - - private static final Mono MONO_SUCCESS = Mono.just(Success.INSTANCE); - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/AbstractRSocketExchange.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/AbstractRSocketExchange.java deleted file mode 100644 index 584cf4ff..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/AbstractRSocketExchange.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.filter; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public abstract class AbstractRSocketExchange implements RSocketExchange { - - private final Map attributes = new ConcurrentHashMap<>(); - - @Override - public Map getAttributes() { - return this.attributes; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/FilterChain.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/FilterChain.java deleted file mode 100644 index 53fcafd5..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/FilterChain.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.filter; - -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.filter.RSocketFilter.Success; - -/** - * Contract to allow a {@link RSocketFilter} to delegate to the next in the chain. - * - * @author Spencer Gibb - */ -public interface FilterChain { - - /** - * Delegate to the next {@code WebFilter} in the chain. - * @param exchange the current server exchange - * @return {@code Mono} to indicate when request handling is complete - */ - Mono filter(E exchange); - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/RSocketExchange.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/RSocketExchange.java deleted file mode 100644 index bb30820e..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/RSocketExchange.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.filter; - -import java.util.Map; - -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -public interface RSocketExchange { - - /** - * Return a mutable map of request attributes for the current exchange. - * @return current attributes. - */ - Map getAttributes(); - - /** - * Return the request attribute value if present. - * @param name the attribute name - * @param the attribute type - * @return the attribute value - */ - @SuppressWarnings("unchecked") - @Nullable - default T getAttribute(String name) { - return (T) getAttributes().get(name); - } - - /** - * Return the request attribute value or if not present raise an - * {@link IllegalArgumentException}. - * @param name the attribute name - * @param the attribute type - * @return the attribute value - */ - @SuppressWarnings("unchecked") - default T getRequiredAttribute(String name) { - T value = getAttribute(name); - Assert.notNull(value, () -> "Required attribute '" + name + "' is missing"); - return value; - } - - /** - * Return the request attribute value, or a default, fallback value. - * @param name the attribute name - * @param defaultValue a default value to return instead - * @param the attribute type - * @return the attribute value - */ - @SuppressWarnings("unchecked") - default T getAttributeOrDefault(String name, T defaultValue) { - return (T) getAttributes().getOrDefault(name, defaultValue); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/RSocketFilter.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/RSocketFilter.java deleted file mode 100644 index 7833a9b4..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/filter/RSocketFilter.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.filter; - -import reactor.core.publisher.Mono; - -/** - * Contract for interception-style, chained processing of Web requests that may be used to - * implement cross-cutting, application-agnostic requirements such as security, timeouts, - * and others. - * - * Copied from WebFilter - * - * @author Spencer Gibb - */ -public interface RSocketFilter> { - - /** - * Enum to signal successful end of chain reached without the end being empty, i.e. - * Mono<Void> via Mono.empty(). This is because at the end of the chain an - * actual value needs to be returned. We can map success, but not empty. - */ - enum Success { - - INSTANCE - - } // should never have more than one value - - /** - * Process the Web request and (optionally) delegate to the next {@code RSocketFilter} - * through the given {@link FilterChain}. - * @param exchange the current RSocket exchange - * @param chain provides a way to delegate to the next filter - * @return {@code Mono} to indicate when request processing is complete. - */ - Mono filter(E exchange, FC chain); - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/metrics/MicrometerResponderRSocket.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/metrics/MicrometerResponderRSocket.java deleted file mode 100644 index 3c7b981b..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/metrics/MicrometerResponderRSocket.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.metrics; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import io.micrometer.core.instrument.Counter; -import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tag; -import io.micrometer.core.instrument.Tags; -import io.micrometer.core.instrument.Timer; -import io.rsocket.Payload; -import io.rsocket.RSocket; -import io.rsocket.ResponderRSocket; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.core.publisher.SignalType; - -import org.springframework.util.Assert; - -import static reactor.core.publisher.SignalType.CANCEL; -import static reactor.core.publisher.SignalType.ON_COMPLETE; -import static reactor.core.publisher.SignalType.ON_ERROR; - -public class MicrometerResponderRSocket implements ResponderRSocket { - - private static final Log log = LogFactory.getLog(MicrometerResponderRSocket.class); - - private final RSocket delegate; - - private final InteractionCounters metadataPush; - - private final InteractionCounters requestChannel; - - private final InteractionCounters requestFireAndForget; - - private final InteractionTimers requestResponse; - - private final InteractionCounters requestStream; - - /** - * Creates a new {@link RSocket}. - * @param delegate the {@link RSocket} to delegate to - * @param meterRegistry the {@link MeterRegistry} to use - * @param tags additional tags to attach to {@link Meter}s - * @throws IllegalArgumentException if {@code delegate} or {@code meterRegistry} is - * {@code null} - */ - public MicrometerResponderRSocket(RSocket delegate, MeterRegistry meterRegistry, - Tag... tags) { - Assert.notNull(delegate, "delegate must not be null"); - Assert.notNull(meterRegistry, "meterRegistry must not be null"); - - this.delegate = delegate; - this.metadataPush = new InteractionCounters(meterRegistry, "metadata.push", tags); - this.requestChannel = new InteractionCounters(meterRegistry, "request.channel", - tags); - this.requestFireAndForget = new InteractionCounters(meterRegistry, "request.fnf", - tags); - this.requestResponse = new InteractionTimers(meterRegistry, "request.response", - tags); - this.requestStream = new InteractionCounters(meterRegistry, "request.stream", - tags); - } - - @Override - public void dispose() { - delegate.dispose(); - } - - @Override - public Mono fireAndForget(Payload payload) { - return delegate.fireAndForget(payload).doFinally(requestFireAndForget); - } - - @Override - public Mono metadataPush(Payload payload) { - return delegate.metadataPush(payload).doFinally(metadataPush); - } - - @Override - public Mono onClose() { - return delegate.onClose(); - } - - @Override - public Flux requestChannel(Publisher payloads) { - return delegate.requestChannel(payloads).doFinally(requestChannel); - } - - @Override - public Mono requestResponse(Payload payload) { - return Mono.defer(() -> { - Timer.Sample sample = requestResponse.start(); - - return delegate.requestResponse(payload) - .doFinally(signalType -> requestResponse.accept(sample, signalType)); - }); - } - - @Override - public Flux requestStream(Payload payload) { - return delegate.requestStream(payload).doFinally(requestStream); - } - - @Override - public Flux requestChannel(Payload payload, Publisher payloads) { - if (delegate instanceof ResponderRSocket) { - ResponderRSocket rSocket = (ResponderRSocket) delegate; - return rSocket.requestChannel(payload, payloads).doFinally(requestChannel); - } - return delegate.requestChannel(payloads).doFinally(requestChannel); - } - - private static final class InteractionCounters implements Consumer { - - private final Counter cancel; - - private final Counter onComplete; - - private final Counter onError; - - private InteractionCounters(MeterRegistry meterRegistry, String interactionModel, - Tag... tags) { - this.cancel = counter(meterRegistry, interactionModel, CANCEL, tags); - this.onComplete = counter(meterRegistry, interactionModel, ON_COMPLETE, tags); - this.onError = counter(meterRegistry, interactionModel, ON_ERROR, tags); - } - - @Override - public void accept(SignalType signalType) { - switch (signalType) { - case CANCEL: - if (this.cancel != null) { - this.cancel.increment(); - } - break; - case ON_COMPLETE: - if (this.onComplete != null) { - this.onComplete.increment(); - } - break; - case ON_ERROR: - if (this.onError != null) { - this.onError.increment(); - } - break; - } - } - - private Counter counter(MeterRegistry meterRegistry, String interactionModel, - SignalType signalType, Tag... tags) { - - Tags withType = Tags.of(tags).and("signal.type", signalType.name()); - try { - return meterRegistry.counter("rsocket." + interactionModel, withType); - } - catch (Exception e) { - if (log.isTraceEnabled()) { - log.trace("Error creating counter with tags: " + withType, e); - } - return null; - } - } - - } - - private static final class InteractionTimers - implements BiConsumer { - - private final Timer cancel; - - private final MeterRegistry meterRegistry; - - private final Timer onComplete; - - private final Timer onError; - - private InteractionTimers(MeterRegistry meterRegistry, String interactionModel, - Tag... tags) { - this.meterRegistry = meterRegistry; - - this.cancel = timer(meterRegistry, interactionModel, CANCEL, tags); - this.onComplete = timer(meterRegistry, interactionModel, ON_COMPLETE, tags); - this.onError = timer(meterRegistry, interactionModel, ON_ERROR, tags); - } - - @Override - public void accept(Timer.Sample sample, SignalType signalType) { - switch (signalType) { - case CANCEL: - if (this.cancel != null) { - sample.stop(this.cancel); - } - break; - case ON_COMPLETE: - if (this.onComplete != null) { - sample.stop(this.onComplete); - } - break; - case ON_ERROR: - if (this.onError != null) { - sample.stop(this.onError); - } - break; - } - } - - Timer.Sample start() { - return Timer.start(meterRegistry); - } - - private static Timer timer(MeterRegistry meterRegistry, String interactionModel, - SignalType signalType, Tag... tags) { - - Tags withType = Tags.of(tags).and("signal.type", signalType.name()); - try { - return meterRegistry.timer("rsocket." + interactionModel, withType); - } - catch (Exception e) { - if (log.isTraceEnabled()) { - log.trace("Error creating timer with tags: " + withType, e); - } - return null; - } - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/metrics/MicrometerResponderRSocketInterceptor.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/metrics/MicrometerResponderRSocketInterceptor.java deleted file mode 100644 index f2363211..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/metrics/MicrometerResponderRSocketInterceptor.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.metrics; - -import java.util.Objects; - -import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tag; -import io.rsocket.RSocket; -import io.rsocket.plugins.RSocketInterceptor; - -public class MicrometerResponderRSocketInterceptor implements RSocketInterceptor { - - private final MeterRegistry meterRegistry; - - private final Tag[] tags; - - /** - * Creates a new {@link RSocketInterceptor}. - * @param meterRegistry the {@link MeterRegistry} to use to create {@link Meter}s. - * @param tags the additional tags to attach to each {@link Meter} - * @throws NullPointerException if {@code meterRegistry} is {@code null} - */ - public MicrometerResponderRSocketInterceptor(MeterRegistry meterRegistry, - Tag... tags) { - this.meterRegistry = Objects.requireNonNull(meterRegistry, - "meterRegistry must not be null"); - this.tags = tags; - } - - @Override - public MicrometerResponderRSocket apply(RSocket delegate) { - Objects.requireNonNull(delegate, "delegate must not be null"); - - return new MicrometerResponderRSocket(delegate, meterRegistry, tags); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/DefaultRoute.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/DefaultRoute.java deleted file mode 100644 index 33271ba9..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/DefaultRoute.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.route; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.cloud.gateway.rsocket.core.GatewayExchange; -import org.springframework.cloud.gateway.rsocket.core.GatewayFilter; -import org.springframework.cloud.gateway.rsocket.support.AsyncPredicate; -import org.springframework.core.style.ToStringCreator; -import org.springframework.util.Assert; - -/** - * @author Spencer Gibb - */ -public class DefaultRoute implements Route { - - private final String id; - - private final RouteSetup targetMetadata; - - private final int order; - - private final AsyncPredicate predicate; - - private final List gatewayFilters; - - public static Builder builder() { - return new Builder(); - } - - private DefaultRoute(String id, RouteSetup targetMetadata, int order, - AsyncPredicate predicate, - List gatewayFilters) { - this.id = id; - this.targetMetadata = targetMetadata; - this.order = order; - this.predicate = predicate; - this.gatewayFilters = gatewayFilters; - } - - public String getId() { - return this.id; - } - - public int getOrder() { - return order; - } - - public AsyncPredicate getPredicate() { - return this.predicate; - } - - public List getFilters() { - return Collections.unmodifiableList(this.gatewayFilters); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Route route = (Route) o; - return Objects.equals(id, route.getId()) - && Objects.equals(order, route.getOrder()) - && Objects.equals(predicate, route.getPredicate()) - && Objects.equals(gatewayFilters, route.getFilters()); - } - - @Override - public int hashCode() { - return Objects.hash(id, targetMetadata, predicate, gatewayFilters); - } - - @Override - public String toString() { - return new ToStringCreator(this).append("id", id) - .append("targetMetadata", targetMetadata).append("order", order) - .append("predicate", predicate).append("gatewayFilters", gatewayFilters) - .toString(); - } - - public static class Builder { - - protected String id; - - protected RouteSetup routingMetadata; - - protected int order = 0; - - protected AsyncPredicate predicate; - - protected List gatewayFilters = new ArrayList<>(); - - protected Builder() { - } - - public Builder id(String id) { - this.id = id; - return this; - } - - public String getId() { - return id; - } - - public Builder order(int order) { - this.order = order; - return this; - } - - public AsyncPredicate getPredicate() { - return this.predicate; - } - - public Builder routingMetadata(RouteSetup routingMetadata) { - this.routingMetadata = routingMetadata; - return this; - } - - public Builder setFilters(List gatewayFilters) { - this.gatewayFilters = gatewayFilters; - return this; - } - - public Builder filter(GatewayFilter gatewayFilter) { - this.gatewayFilters.add(gatewayFilter); - return this; - } - - public Builder filters(Collection gatewayFilters) { - this.gatewayFilters.addAll(gatewayFilters); - return this; - } - - public Builder filters(GatewayFilter... gatewayFilters) { - return filters(Arrays.asList(gatewayFilters)); - } - - public Builder predicate(AsyncPredicate predicate) { - this.predicate = predicate; - return this; - } - - public Builder and(AsyncPredicate predicate) { - Assert.notNull(this.predicate, "can not call and() on null predicate"); - this.predicate = this.predicate.and(predicate); - return this; - } - - public Builder or(AsyncPredicate predicate) { - Assert.notNull(this.predicate, "can not call or() on null predicate"); - this.predicate = this.predicate.or(predicate); - return this; - } - - public Builder negate() { - Assert.notNull(this.predicate, "can not call negate() on null predicate"); - this.predicate = this.predicate.negate(); - return this; - } - - public Route build() { - Assert.notNull(this.id, "id can not be null"); - Assert.notNull(this.routingMetadata, "targetMetadata can not be null"); - Assert.notNull(this.predicate, "predicate can not be null"); - - return new DefaultRoute(this.id, this.routingMetadata, this.order, predicate, - this.gatewayFilters); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/Route.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/Route.java deleted file mode 100644 index 404fff23..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/Route.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.route; - -import java.util.List; - -import org.springframework.cloud.gateway.rsocket.core.GatewayExchange; -import org.springframework.cloud.gateway.rsocket.core.GatewayFilter; -import org.springframework.cloud.gateway.rsocket.support.AsyncPredicate; -import org.springframework.core.Ordered; - -/** - * @author Spencer Gibb - */ -public interface Route extends Ordered { - - String getId(); - - default int getOrder() { - return 0; - } - - AsyncPredicate getPredicate(); - - List getFilters(); - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/Routes.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/Routes.java deleted file mode 100644 index 47bdeb9e..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/route/Routes.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.route; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.core.GatewayExchange; - -/** - * @author Spencer Gibb - */ -public interface Routes { - - /** log. */ - Log log = LogFactory.getLog(Routes.class); - - Flux getRoutes(); - - default Mono findRoute(GatewayExchange exchange) { - return getRoutes() - // individually filter routes so that filterWhen error delaying is not a - // problem - .concatMap(route -> Mono.just(route).filterWhen(r -> { - // add the current route we are testing - // TODO: exchange attributes - // exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, - // r.getId()); - return r.getPredicate().apply(exchange); - }) - // instead of immediately stopping main flux due to error, log and - // swallow it - .doOnError(e -> log.error( - "Error applying predicate for route: " + route.getId(), - e)) - .onErrorResume(e -> Mono.empty())) - .next().map(route -> { - if (log.isDebugEnabled()) { - log.debug("Route matched: " + route.getId()); - } - return route; - }); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/LoadBalancerFactory.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/LoadBalancerFactory.java deleted file mode 100644 index 2cc6f1d6..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/LoadBalancerFactory.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.routing; - -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; - -import io.rsocket.RSocket; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Mono; -import reactor.util.function.Tuple2; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; - -public class LoadBalancerFactory { - - private static final Log log = LogFactory.getLog(LoadBalancerFactory.class); - - private final RoutingTable routingTable; - - public LoadBalancerFactory(RoutingTable routingTable) { - this.routingTable = routingTable; - } - - public List> find(TagsMetadata tagsMetadata) { - List> rSockets = this.routingTable - .findRSockets(tagsMetadata); - return rSockets; - } - - // TODO: potentially GatewayExchange or return a new Result Object? - public Mono> choose(TagsMetadata tagsMetadata) { - List> rSockets = this.routingTable - .findRSockets(tagsMetadata); - // TODO: change loadbalancer impl based on tags - // TODO: cache loadbalancers based on tags - return new RoundRobinLoadBalancer(tagsMetadata).apply(rSockets); - } - - // TODO: Flux as input? - // TODO: reuse commons load balancer? - public interface LoadBalancer extends - Function>, Mono>> { - - } - - public static class RoundRobinLoadBalancer implements LoadBalancer { - - private final TagsMetadata tagsMetadata; - - private final AtomicInteger position; - - public RoundRobinLoadBalancer(TagsMetadata tagsMetadata) { - this(tagsMetadata, new Random().nextInt(1000)); - } - - public RoundRobinLoadBalancer(TagsMetadata tagsMetadata, int seedPosition) { - this.tagsMetadata = tagsMetadata; - this.position = new AtomicInteger(seedPosition); - } - - @Override - public Mono> apply( - List> rSockets) { - if (rSockets.isEmpty()) { - if (log.isWarnEnabled()) { - log.warn("No servers available for: " + this.tagsMetadata); - } - return Mono.empty(); - } - // TODO: enforce order? - int pos = Math.abs(this.position.incrementAndGet()); - - Tuple2 tuple = rSockets.get(pos % rSockets.size()); - return Mono.just(tuple); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTable.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTable.java deleted file mode 100644 index cbcaca67..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTable.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.routing; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; - -import io.rsocket.RSocket; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.roaringbitmap.IntConsumer; -import org.roaringbitmap.RoaringBitmap; -import reactor.core.Disposable; -import reactor.core.publisher.DirectProcessor; -import reactor.core.publisher.FluxSink; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey; -import org.springframework.core.style.ToStringCreator; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * The RoutingTable handles all RSocket connections that have been made that have - * associated RouteSetup metadata. RSocket connections can then be found based on - * Forwarding metadata. When a new RSocket is registered, a RegisteredEvent is pushed onto - * a DirectProcessor that is acting as an event bus for registered Consumers. - */ -public class RoutingTable { - - private static final Log log = LogFactory.getLog(RoutingTable.class); - - AtomicInteger internalRouteId = new AtomicInteger(); - - final Map internalRouteIdToRouteId = new ConcurrentHashMap<>(); - - final Map tagsToBitmaps = new ConcurrentHashMap<>(); - - final Map routeEntries = new ConcurrentHashMap<>(); - - private final DirectProcessor registeredEvents = DirectProcessor - .create(); - - private final FluxSink registeredEventsSink = registeredEvents - .sink(FluxSink.OverflowStrategy.DROP); - - public RoutingTable() { - } - - // TODO: Mono? - public void register(TagsMetadata tagsMetadata, RSocket rsocket) { - register(new RouteEntry(rsocket, tagsMetadata)); - } - - private void register(RouteEntry routeEntry) { - if (log.isInfoEnabled()) { - log.info("Registering RSocket: " + routeEntry.tagsMetadata); - } - - // TODO: only register new route if timestamp is newer - String routeId = routeEntry.getRouteId(); - - if (routeEntries.containsKey(routeId)) { - throw new IllegalStateException("Route Id already registered: " + routeId); - } - - int internalId = internalRouteId.incrementAndGet(); - internalRouteIdToRouteId.put(internalId, routeId); - routeEntries.put(routeId, routeEntry); - - routeEntry.getTags().forEach((key, value) -> { - // TODO: deal with string keys? - RoaringBitmap bitmap = tagsToBitmaps.computeIfAbsent(new TagKey(key, value), - k -> new RoaringBitmap()); - bitmap.add(internalId); - }); - - registeredEventsSink.next(new RegisteredEvent(routeEntry)); - } - - public boolean deregister(TagsMetadata metadata) { - Assert.notNull(metadata, "metadata may not be null"); - String routeId = metadata.getRouteId(); - if (!StringUtils.hasText(routeId)) { - if (log.isDebugEnabled()) { - log.debug("Unable to deregister, no RouteId: " + metadata); - } - return false; - } - if (log.isInfoEnabled()) { - log.info("Deregistering RSocket: " + metadata); - } - - TagsMetadata findByRouteId = TagsMetadata.builder() - .with(WellKnownKey.ROUTE_ID, routeId).build(); - RoaringBitmap found = find(findByRouteId); - - if (found.isEmpty() || found.getLongCardinality() > 1) { - if (log.isWarnEnabled()) { - log.warn("Unable to deregister " + metadata + ", found: " - + found.getLongCardinality()); - } - return false; - } - - int internalId = found.first(); - internalRouteIdToRouteId.remove(internalId); - routeEntries.remove(routeId); - - metadata.getTags().forEach((key, value) -> { - // TODO: deal with string keys? - TagKey tagKey = new TagKey(key, value); - if (tagsToBitmaps.containsKey(tagKey)) { - RoaringBitmap bitmap = tagsToBitmaps.get(tagKey); - bitmap.remove(internalId); - } - }); - - // TODO: deregistered event - return true; - } - - /** - * Finds routeIds of matching routes. - * @param tagsMetadata tags to match. - * @return all matching routeIds or empty list. - */ - public Set findRouteIds(TagsMetadata tagsMetadata) { - RoaringBitmap found = find(tagsMetadata); - if (found.isEmpty()) { - return Collections.emptySet(); - } - HashSet routeIds = new HashSet<>(); - found.forEach((IntConsumer) internalId -> { - String routeId = internalRouteIdToRouteId.get(internalId); - routeIds.add(routeId); - }); - return routeIds; - } - - /** - * Finds tuples of routeIds and RSockets of matching routes. - * @param tagsMetadata tags to match. - * @return all matching routeId and RSocket tuples or empty list. - */ - public List> findRSockets(TagsMetadata tagsMetadata) { - RoaringBitmap found = find(tagsMetadata); - if (found.isEmpty()) { - return Collections.emptyList(); - } - ArrayList> rSockets = new ArrayList<>(); - found.forEach((IntConsumer) internalId -> { - String routeId = internalRouteIdToRouteId.get(internalId); - RouteEntry routeEntry = routeEntries.get(routeId); - RSocket rSocket = routeEntry.getRSocket(); - rSockets.add(Tuples.of(routeId, rSocket)); - }); - return rSockets; - } - - /** - * Finds internal ids of routes. - * @param tagsMetadata tags to match - * @return bitmap of all internal ids of routes. - */ - RoaringBitmap find(TagsMetadata tagsMetadata) { - RoaringBitmap found = new RoaringBitmap(); - AtomicBoolean first = new AtomicBoolean(true); - tagsMetadata.getTags().forEach((key, value) -> { - TagKey tagKey = new TagKey(key, value); - if (tagsToBitmaps.containsKey(tagKey)) { - RoaringBitmap search = tagsToBitmaps.get(tagKey); - if (first.get()) { - // initiliaze found bitmap with current search - found.or(search); - first.compareAndSet(true, false); - } - else { - found.and(search); - } - } - }); - return found; - } - - public Disposable addListener(Consumer consumer) { - return this.registeredEvents.subscribe(consumer); - } - - public static class RegisteredEvent { - - private final RouteEntry routeEntry; - - public RegisteredEvent(RouteEntry routeEntry) { - Assert.notNull(routeEntry, "routeEntry may not be null"); - this.routeEntry = routeEntry; - } - - public TagsMetadata getRoutingMetadata() { - return this.routeEntry.getTagsMetadata(); - } - - public RSocket getRSocket() { - return this.routeEntry.getRSocket(); - } - - } - - static class RouteEntry { - - private final RSocket rSocket; - - private final TagsMetadata tagsMetadata; - - private final Long timestamp; - - RouteEntry(RSocket rSocket, TagsMetadata tagsMetadata) { - this(rSocket, tagsMetadata, System.currentTimeMillis()); - } - - RouteEntry(RSocket rSocket, TagsMetadata tagsMetadata, Long timestamp) { - Assert.notNull(tagsMetadata, "tagsMetadata may not be null"); - Assert.notNull(rSocket, "RSocket may not be null"); - this.rSocket = rSocket; - this.tagsMetadata = tagsMetadata; - this.timestamp = timestamp; - } - - public RSocket getRSocket() { - return this.rSocket; - } - - public TagsMetadata getTagsMetadata() { - return this.tagsMetadata; - } - - public Long getTimestamp() { - return this.timestamp; - } - - public String getRouteId() { - return this.tagsMetadata.getRouteId(); - } - - public Map getTags() { - return this.getTagsMetadata().getTags(); - } - - @Override - public String toString() { - // @formatter:off - return new ToStringCreator(this) - .append("rSocket", rSocket) - .append("tagsMetadata", tagsMetadata) - .toString(); - // @formatter:on - } - - } - - static class TagKey { - - final TagsMetadata.Key key; - - final String value; - - TagKey(TagsMetadata.Key key, String value) { - // TODO: Assert non null - this.key = key; - this.value = value.toLowerCase(); - } - - public TagsMetadata.Key getKey() { - return this.key; - } - - public String getValue() { - return this.value; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - TagKey that = (TagKey) o; - return Objects.equals(this.key, that.key) - && Objects.equals(this.value, that.value); - } - - @Override - public int hashCode() { - return Objects.hash(this.key, this.value); - } - - @Override - public String toString() { - return new ToStringCreator(this).append("key", key).append("value", value) - .toString(); - - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableRoutes.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableRoutes.java deleted file mode 100644 index bbc09c68..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableRoutes.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.routing; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.core.GatewayExchange; -import org.springframework.cloud.gateway.rsocket.core.GatewayFilter; -import org.springframework.cloud.gateway.rsocket.route.Route; -import org.springframework.cloud.gateway.rsocket.route.Routes; -import org.springframework.cloud.gateway.rsocket.support.AsyncPredicate; -import org.springframework.core.style.ToStringCreator; - -/** - * View of RoutingTable as Route objects. - */ -public class RoutingTableRoutes - implements Routes, Consumer { - - private static final Log log = LogFactory.getLog(RoutingTableRoutes.class); - - private Map routes = new ConcurrentHashMap<>(); - - private final RoutingTable routingTable; - - public RoutingTableRoutes(RoutingTable routingTable) { - this.routingTable = routingTable; - this.routingTable.addListener(this); - } - - @Override - public Flux getRoutes() { - // TODO: sorting? - // TODO: caching - - Collection routeCollection = routes.values(); - if (log.isDebugEnabled()) { - log.debug("Found routes: " + routeCollection); - } - return Flux.fromIterable(routeCollection); - } - - @Override - public void accept(RoutingTable.RegisteredEvent registeredEvent) { - TagsMetadata routingMetadata = registeredEvent.getRoutingMetadata(); - String routeId = routingMetadata.getRouteId(); - - routes.computeIfAbsent(routeId, key -> createRoute(routeId)); - } - - private Route createRoute(String routeId) { - AsyncPredicate predicate = new RoutIdPredicate(routingTable, - routeId); - - RegistryRoute route = new RegistryRoute(routeId, predicate); - - if (log.isDebugEnabled()) { - log.debug("Created Route for registered service " + route); - } - - return route; - } - - static class RoutIdPredicate implements AsyncPredicate { - - private final RoutingTable routingTable; - - private final String routeId; - - RoutIdPredicate(RoutingTable routingTable, String routeId) { - this.routingTable = routingTable; - this.routeId = routeId; - } - - @Override - public Publisher apply(GatewayExchange exchange) { - // TODO: standard predicates - // TODO: allow customized predicates - Set routeIds = routingTable - .findRouteIds(exchange.getRoutingMetadata()); - return Mono.just(routeIds.contains(routeId)); - } - - @Override - public String toString() { - return String.format("[RoutIdPredicate %s]", routeId); - } - - } - - static class RegistryRoute implements Route { - - final String id; - - final AsyncPredicate predicate; - - RegistryRoute(String id, AsyncPredicate predicate) { - this.id = id; - this.predicate = predicate; - } - - @Override - public String getId() { - return this.id; - } - - @Override - public AsyncPredicate getPredicate() { - return this.predicate; - } - - @Override - public List getFilters() { - return Collections.emptyList(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - RegistryRoute that = (RegistryRoute) o; - return Objects.equals(this.id, that.id) - && Objects.equals(this.predicate, that.predicate); - } - - @Override - public int hashCode() { - return Objects.hash(this.id, this.predicate); - } - - @Override - public String toString() { - return new ToStringCreator(this).append("id", id) - .append("predicate", predicate).toString(); - - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableSocketAcceptorFilter.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableSocketAcceptorFilter.java deleted file mode 100644 index ddc968a3..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableSocketAcceptorFilter.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.routing; - -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorExchange; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorFilter; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorFilterChain; -import org.springframework.core.Ordered; - -/** - * Filter that registers the SendingSocket. - */ -public class RoutingTableSocketAcceptorFilter implements SocketAcceptorFilter, Ordered { - - private final RoutingTable routingTable; - - public RoutingTableSocketAcceptorFilter(RoutingTable routingTable) { - this.routingTable = routingTable; - } - - @Override - public Mono filter(SocketAcceptorExchange exchange, - SocketAcceptorFilterChain chain) { - if (exchange.getMetadata() != null) { - // TODO: needed? && - // StringUtils.hasLength(exchange.getMetadata().getServiceName())) { - this.routingTable.register(exchange.getMetadata().getEnrichedTagsMetadata(), - exchange.getSendingSocket()); - } - - return chain.filter(exchange); - } - - @Override - public int getOrder() { - return HIGHEST_PRECEDENCE + 1000; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/GatewaySocketAcceptor.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/GatewaySocketAcceptor.java deleted file mode 100644 index 984fa7ae..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/GatewaySocketAcceptor.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.socketacceptor; - -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.stream.Collectors; - -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tag; -import io.micrometer.core.instrument.Tags; -import io.rsocket.ConnectionSetupPayload; -import io.rsocket.RSocket; -import io.rsocket.SocketAcceptor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.core.GatewayRSocketFactory; -import org.springframework.cloud.gateway.rsocket.metrics.MicrometerResponderRSocket; -import org.springframework.messaging.rsocket.MetadataExtractor; -import org.springframework.util.MimeType; - -public class GatewaySocketAcceptor implements SocketAcceptor { - - private static final Log log = LogFactory.getLog(GatewaySocketAcceptor.class); - - private final SocketAcceptorFilterChain filterChain; - - private final GatewayRSocketFactory rSocketFactory; - - private final MeterRegistry meterRegistry; - - private final BrokerProperties properties; - - private final MetadataExtractor metadataExtractor; - - public GatewaySocketAcceptor(GatewayRSocketFactory rSocketFactory, - List filters, MeterRegistry meterRegistry, - BrokerProperties properties, MetadataExtractor metadataExtractor) { - this.rSocketFactory = rSocketFactory; - this.filterChain = new SocketAcceptorFilterChain(filters); - this.meterRegistry = meterRegistry; - this.properties = properties; - this.metadataExtractor = metadataExtractor; - } - - @Override - @SuppressWarnings("Duplicates") - public Mono accept(ConnectionSetupPayload setup, RSocket sendingSocket) { - if (log.isTraceEnabled()) { - log.trace("accept()"); - } - // decorate GatewayRSocket with metrics - // current gateway id, type requester, service name (from metadata), service id - - Tags requesterTags = Tags.of("gateway.id", properties.getId(), "type", - "requester"); - - Tags metadataTags; - SocketAcceptorExchange exchange; - - Map metadataMap = null; - try { - metadataMap = this.metadataExtractor.extract(setup, - MimeType.valueOf(setup.metadataMimeType())); - } - catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("Error extracting metadata", e); - } - return Mono.error(e); - } - if (metadataMap.containsKey("routesetup")) { - RouteSetup metadata = (RouteSetup) metadataMap.get("routesetup"); - metadataTags = Tags.of("service.name", metadata.getServiceName()) - .and("service.id", metadata.getId().toString()); - // enrich exchange to have metadata - exchange = new SocketAcceptorExchange(setup, - decorate(sendingSocket, requesterTags.and(metadataTags)), metadata); - } - else { - metadataTags = Tags.of("service.name", "UNKNOWN").and("service.id", - "UNKNOWN"); - exchange = new SocketAcceptorExchange(setup, - decorate(sendingSocket, requesterTags)); - } - - Tags responderTags = Tags - .of("gateway.id", properties.getId(), "type", "responder") - .and(metadataTags); - - // decorate with metrics gateway id, type responder, service name, service id - // (instance id) - return this.filterChain.filter(exchange).log( - GatewaySocketAcceptor.class.getName() + ".socket acceptor filter chain", - Level.FINEST).map(success -> { - TagsMetadata tags = exchange.getMetadata().getEnrichedTagsMetadata(); - return decorate(this.rSocketFactory.create(tags), responderTags); - }); - } - - private RSocket decorate(RSocket rSocket, Tags tags) { - Tag[] tagArray = tags.stream().collect(Collectors.toList()).toArray(new Tag[] {}); - return new MicrometerResponderRSocket(rSocket, meterRegistry, tagArray); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorExchange.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorExchange.java deleted file mode 100644 index 0c0f5625..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorExchange.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.socketacceptor; - -import java.math.BigInteger; - -import io.rsocket.ConnectionSetupPayload; -import io.rsocket.RSocket; - -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.cloud.gateway.rsocket.filter.AbstractRSocketExchange; - -public class SocketAcceptorExchange extends AbstractRSocketExchange { - - private final ConnectionSetupPayload setup; - - private final RSocket sendingSocket; - - private final RouteSetup metadata; - - public SocketAcceptorExchange(ConnectionSetupPayload setup, RSocket sendingSocket) { - this(setup, sendingSocket, RouteSetup.of((BigInteger) null, null).build()); - } - - public SocketAcceptorExchange(ConnectionSetupPayload setup, RSocket sendingSocket, - RouteSetup metadata) { - this.setup = setup; - this.sendingSocket = sendingSocket; - this.metadata = metadata; - } - - public ConnectionSetupPayload getSetup() { - return setup; - } - - public RSocket getSendingSocket() { - return sendingSocket; - } - - public RouteSetup getMetadata() { - return metadata; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorFilter.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorFilter.java deleted file mode 100644 index 31923172..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorFilter.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.socketacceptor; - -import org.springframework.cloud.gateway.rsocket.filter.RSocketFilter; - -public interface SocketAcceptorFilter - extends RSocketFilter { - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorFilterChain.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorFilterChain.java deleted file mode 100644 index 470eee62..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorFilterChain.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.socketacceptor; - -import java.util.List; - -import org.springframework.cloud.gateway.rsocket.filter.AbstractFilterChain; - -public class SocketAcceptorFilterChain extends - AbstractFilterChain { - - /** - * Public constructor with the list of filters and the target handler to use. - * @param filters the filters ahead of the handler - */ - public SocketAcceptorFilterChain(List filters) { - super(filters); - } - - public SocketAcceptorFilterChain(List allFilters, - SocketAcceptorFilter currentFilter, SocketAcceptorFilterChain next) { - super(allFilters, currentFilter, next); - } - - @Override - protected SocketAcceptorFilterChain create(List allFilters, - SocketAcceptorFilter currentFilter, SocketAcceptorFilterChain next) { - return new SocketAcceptorFilterChain(allFilters, currentFilter, next); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicate.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicate.java deleted file mode 100644 index af37eddd..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicate.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.socketacceptor; - -import org.springframework.cloud.gateway.rsocket.support.AsyncPredicate; - -public interface SocketAcceptorPredicate extends AsyncPredicate { - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicateFilter.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicateFilter.java deleted file mode 100644 index b9b2df43..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicateFilter.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.socketacceptor; - -import java.util.List; - -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.support.AsyncPredicate; -import org.springframework.core.Ordered; -import org.springframework.util.Assert; - -public class SocketAcceptorPredicateFilter implements SocketAcceptorFilter, Ordered { - - private final AsyncPredicate predicate; - - // TODO: change from List to Flux? - public SocketAcceptorPredicateFilter(List predicates) { - Assert.notNull(predicates, "predicates may not be null"); - if (predicates.isEmpty()) { - predicate = exchange -> Mono.just(true); - } - else { - AsyncPredicate combined = predicates.get(0); - for (SocketAcceptorPredicate p : predicates.subList(1, predicates.size())) { - combined = combined.and(p); - } - predicate = combined; - } - } - - @Override - public int getOrder() { - return HIGHEST_PRECEDENCE + 10000; - } - - @Override - public Mono filter(SocketAcceptorExchange exchange, - SocketAcceptorFilterChain chain) { - return Mono.from(predicate.apply(exchange)).flatMap(test -> { - if (test) { - return chain.filter(exchange); - } - return Mono.empty(); - }); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/support/AsyncPredicate.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/support/AsyncPredicate.java deleted file mode 100644 index 7fdad9ca..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/java/org/springframework/cloud/gateway/rsocket/support/AsyncPredicate.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.support; - -import java.util.function.Function; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.util.Assert; - -/** - * @author Ben Hale - */ -public interface AsyncPredicate extends Function> { - - default AsyncPredicate and(AsyncPredicate other) { - Assert.notNull(other, "other must not be null"); - - return t -> Flux.zip(apply(t), other.apply(t)) - .map(tuple -> tuple.getT1() && tuple.getT2()); - } - - default AsyncPredicate negate() { - return t -> Mono.from(apply(t)).map(b -> !b); - } - - default AsyncPredicate or(AsyncPredicate other) { - Assert.notNull(other, "other must not be null"); - - return t -> Flux.zip(apply(t), other.apply(t)) - .map(tuple -> tuple.getT1() || tuple.getT2()); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/resources/META-INF/spring.factories b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/resources/META-INF/spring.factories deleted file mode 100644 index c7338a85..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,7 +0,0 @@ -# Auto Configure -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.gateway.rsocket.autoconfigure.GatewayRSocketAutoConfiguration - -# Environment Post Processors -org.springframework.boot.env.EnvironmentPostProcessor=\ -org.springframework.cloud.gateway.rsocket.autoconfigure.GatewayRSocketEnvironmentPostProcessor diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorIntegrationTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorIntegrationTests.java deleted file mode 100644 index 64e1e7a8..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorIntegrationTests.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.actuate; - -import java.math.BigInteger; -import java.util.Random; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import reactor.core.publisher.Hooks; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.cloud.gateway.rsocket.cluster.ClusterService; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.SocketUtils; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; -import static org.springframework.cloud.gateway.rsocket.actuate.BrokerActuator.BROKER_INFO_PATH; -import static org.springframework.cloud.gateway.rsocket.actuate.BrokerActuator.ROUTE_JOIN_PATH; -import static org.springframework.cloud.gateway.rsocket.actuate.BrokerActuator.ROUTE_REMOVE_PATH; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT, - properties = { "spring.cloud.gateway.rsocket.cluster.enabled=false", - "spring.cloud.gateway.rsocket.broker.actuator.enabled=true" }) -public class BrokerActuatorIntegrationTests { - - private final Random random = new Random(); - - @Autowired - private RSocketRequester.Builder requesterBuilder; - - @Autowired - private RSocketMessageHandler messageHandler; - - @MockBean - private ClusterService clusterService; - - // @LocalServerPort - private static int port; - - @BeforeClass - public static void init() { - Hooks.onOperatorDebug(); - port = SocketUtils.findAvailableTcpPort(); - System.setProperty("spring.rsocket.server.port", String.valueOf(port)); - } - - @AfterClass - public static void after() { - System.clearProperty("spring.rsocket.server.port"); - } - - @Test - public void brokerInfoWorks() { - long brokerId = random.nextLong(); - - BrokerInfo data = BrokerInfo.of(brokerId).build(); - - Mono result = callActuator(brokerId, BigInteger.class, data, - BROKER_INFO_PATH); - - StepVerifier.create(result).consumeNextWith( - res -> assertThat(res).isNotNull().isEqualTo(BigInteger.valueOf(1234L))) - .verifyComplete(); - - // TODO: assert server side calls worked - } - - @Test - @Ignore // TODO: move to integration tests module - public void routeJoinRemoveWorks() { - long brokerId = random.nextLong(); - long routeId = random.nextLong(); - - RouteJoin data = RouteJoin.builder().brokerId(brokerId).routeId(routeId) - .serviceName("testServiceName").build(); - - RSocketRequester requester = getRequester(brokerId); - Mono result = callActuator(requester, brokerId, RouteJoin.class, data, - ROUTE_JOIN_PATH); - - StepVerifier.create(result) - .consumeNextWith(res -> assertThat(res).isNotNull().isEqualTo(data)) - .verifyComplete(); - // TODO: assert server side calls worked - - routeRemoveWorks(requester, routeId); - } - - public void routeRemoveWorks(RSocketRequester requester, long routeId) { - long brokerId = random.nextLong(); - RouteRemove data = RouteRemove.builder().brokerId(brokerId).routeId(routeId) - .build(); - - Mono result = callActuator(requester, brokerId, Boolean.class, data, - ROUTE_REMOVE_PATH); - - StepVerifier.create(result).consumeNextWith(res -> assertThat(res).isTrue()) - .verifyComplete(); - // TODO: assert server side calls worked - - result = callActuator(brokerId, Boolean.class, data, ROUTE_REMOVE_PATH); - - StepVerifier.create(result).consumeNextWith(res -> assertThat(res).isTrue()) - .verifyComplete(); - } - - @Test - @Ignore // TODO: move to integration tests module - public void routeJoinCloseDeregisters() { - long brokerId = random.nextLong(); - long routeId = random.nextLong(); - - RouteJoin data = RouteJoin.builder().brokerId(brokerId).routeId(routeId) - .serviceName("testServiceName").build(); - - RSocketRequester requester = getRequester(brokerId); - Mono result = callActuator(requester, brokerId, RouteJoin.class, data, - ROUTE_JOIN_PATH); - - result.block(); - StepVerifier.create(result) - .consumeNextWith(res -> assertThat(res).isNotNull().isEqualTo(data)) - .verifyComplete(); - - requester.rsocket().dispose(); - - // TODO: assert server side calls worked - } - - private Mono callActuator(long brokerId, Class type, D data, - String path) { - RSocketRequester requester = getRequester(brokerId); - - return callActuator(requester, brokerId, type, data, path); - } - - private Mono callActuator(RSocketRequester requester, long brokerId, - Class type, D data, String path) { - - Forwarding forwarding = Forwarding.of(brokerId).serviceName("gateway") - .disableProxy().build(); - - return requester.route(path).metadata(forwarding, Forwarding.FORWARDING_MIME_TYPE) - .data(data).retrieveMono(type); - } - - private RSocketRequester getRequester(long brokerId) { - RouteSetup routeSetup = RouteSetup.of(brokerId, "gateway") - .with("proxy", Boolean.FALSE.toString()).build(); - // mimic rsocket client autoconfig - return requesterBuilder - .setupMetadata(routeSetup, RouteSetup.ROUTE_SETUP_MIME_TYPE) - .rsocketFactory(rsocketFactory -> rsocketFactory - .acceptor(messageHandler.responder())) - .connectTcp("localhost", port).block(); - } - - @SpringBootConfiguration - @EnableAutoConfiguration - static class Config { - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorRegistrarTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorRegistrarTests.java deleted file mode 100644 index 0a958b8b..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/actuate/BrokerActuatorRegistrarTests.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.actuate; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT, - properties = { "spring.rsocket.server.port=0", - "spring.cloud.gateway.rsocket.route-id=55", - "spring.cloud.gateway.rsocket.service-name=gateway" }) -public class BrokerActuatorRegistrarTests { - - @Autowired - private BrokerActuatorHandlerRegistration registrar; - - @Test - public void test() { - } - - @SpringBootConfiguration - @EnableAutoConfiguration - static class Config { - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketAutoConfigurationTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketAutoConfigurationTests.java deleted file mode 100644 index cae682d5..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/autoconfigure/GatewayRSocketAutoConfigurationTests.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.autoconfigure; - -import io.rsocket.SocketAcceptor; -import org.junit.Test; - -import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration; -import org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration; -import org.springframework.boot.rsocket.context.RSocketServerBootstrap; -import org.springframework.boot.rsocket.server.RSocketServer; -import org.springframework.boot.rsocket.server.RSocketServerFactory; -import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; -import org.springframework.cloud.gateway.rsocket.common.autoconfigure.GatewayRSocketCommonAutoConfiguration; -import org.springframework.cloud.gateway.rsocket.core.GatewayServerRSocketFactoryProcessor; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTableRoutes; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTableSocketAcceptorFilter; -import org.springframework.cloud.gateway.rsocket.socketacceptor.GatewaySocketAcceptor; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorPredicate; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorPredicateFilter; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class GatewayRSocketAutoConfigurationTests { - - @Test - public void gatewayRSocketConfigured() { - new ReactiveWebApplicationContextRunner().withUserConfiguration(MyConfig.class) - .withSystemProperties("spring.cloud.gateway.rsocket.route-id=11") - .withConfiguration( - AutoConfigurations.of(RSocketStrategiesAutoConfiguration.class, - RSocketMessagingAutoConfiguration.class, - GatewayRSocketCommonAutoConfiguration.class, - GatewayRSocketAutoConfiguration.class, - CompositeMeterRegistryAutoConfiguration.class, - MetricsAutoConfiguration.class)) - .run(context -> assertThat(context).hasSingleBean(RoutingTable.class) - .hasSingleBean(RoutingTableRoutes.class) - .hasSingleBean(RoutingTableSocketAcceptorFilter.class) - .hasSingleBean(GatewayServerRSocketFactoryProcessor.class) - .hasSingleBean(BrokerProperties.class) - .hasSingleBean(GatewaySocketAcceptor.class) - .hasSingleBean(SocketAcceptorPredicateFilter.class) - .hasSingleBean(RSocketServerBootstrap.class) - .doesNotHaveBean(SocketAcceptorPredicate.class)); - } - - @Configuration - protected static class MyConfig { - - @Bean - RSocketServerFactory rSocketServerFactory() { - RSocketServerFactory serverFactory = mock(RSocketServerFactory.class); - when(serverFactory.create(any(SocketAcceptor.class))) - .thenReturn(mock(RSocketServer.class)); - return serverFactory; - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterServiceTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterServiceTests.java deleted file mode 100644 index 0b57577f..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/cluster/ClusterServiceTests.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.cluster; - -import org.junit.Test; - -import org.springframework.cloud.gateway.rsocket.actuate.BrokerInfo; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ClusterServiceTests { - - @Test - public void registerIncomingWorks() { - ClusterService routingTable = new ClusterService(); - - BrokerInfo brokerInfo = BrokerInfo.of(1L).timestamp(100L).build(); - boolean result = routingTable.registerIncoming(brokerInfo); - - String brokerId = brokerInfo.getBrokerId().toString(); - assertThat(result).isTrue(); - assertThat(routingTable.incomingBrokers).containsKey(brokerId); - - brokerInfo = BrokerInfo.of(1L).timestamp(10L).build(); - result = routingTable.registerIncoming(brokerInfo); - assertThat(result).isFalse(); - assertThat(routingTable.incomingBrokers.get(brokerId)).isNotNull() - .extracting(ClusterService.BrokerEntry::getTimestamp).isEqualTo(100L); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketIntegrationTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketIntegrationTests.java deleted file mode 100644 index 454230bf..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketIntegrationTests.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import java.time.Duration; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import reactor.core.publisher.Hooks; -import reactor.test.StepVerifier; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.rsocket.RSocketProperties; -import org.springframework.boot.rsocket.context.RSocketServerBootstrap; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.cloud.gateway.rsocket.test.PingPongApp; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.util.SocketUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = PingPongApp.class, - properties = { "ping.take=10", "ping.subscribe=false" }, - webEnvironment = WebEnvironment.RANDOM_PORT) -public class GatewayRSocketIntegrationTests { - - private static int port; - - @Autowired - private PingPongApp.Ping ping; - - @Autowired - private PingPongApp.Pong pong; - - @Autowired - private RSocketProperties properties; - - @Autowired - private PingPongApp.MySocketAcceptorFilter mySocketAcceptorFilter; - - @Autowired - private RSocketServerBootstrap server; - - @BeforeClass - public static void init() { - Hooks.onOperatorDebug(); - port = SocketUtils.findAvailableTcpPort(); - System.setProperty("spring.rsocket.server.port", String.valueOf(port)); - } - - @AfterClass - public static void after() { - System.clearProperty("spring.rsocket.server.port"); - } - - @Test - public void contextLoads() { - // @formatter:off - StepVerifier.create(ping.getPongFlux()) - .expectSubscription() - .then(() -> server.stop()) - .thenConsumeWhile(s -> true) - .expectComplete() - .verify(Duration.ofSeconds(20)); - // @formatter:on - - assertThat(ping.getPongsReceived()).isGreaterThan(0); - assertThat(pong.getPingsReceived()).isGreaterThan(0); - Object server = properties.getServer(); - Object port = ReflectionTestUtils.invokeGetterMethod(server, "port"); - assertThat(port).isNotEqualTo(7002); - assertThat(mySocketAcceptorFilter.invoked()).isTrue(); - assertThat(this.server.isRunning()).isFalse(); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketTests.java deleted file mode 100644 index dc7bfb79..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/core/GatewayRSocketTests.java +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.core; - -import java.time.Duration; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Function; - -import io.micrometer.core.instrument.Tags; -import io.micrometer.core.instrument.simple.SimpleMeterRegistry; -import io.rsocket.Payload; -import io.rsocket.RSocket; -import io.rsocket.util.DefaultPayload; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Before; -import org.junit.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.core.publisher.MonoProcessor; -import reactor.test.StepVerifier; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; - -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.Metadata; -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey; -import org.springframework.cloud.gateway.rsocket.common.test.MetadataEncoder; -import org.springframework.cloud.gateway.rsocket.route.DefaultRoute; -import org.springframework.cloud.gateway.rsocket.route.Route; -import org.springframework.cloud.gateway.rsocket.route.Routes; -import org.springframework.cloud.gateway.rsocket.routing.LoadBalancerFactory; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.messaging.rsocket.DefaultMetadataExtractor; -import org.springframework.messaging.rsocket.MetadataExtractor; -import org.springframework.messaging.rsocket.PayloadUtils; -import org.springframework.messaging.rsocket.RSocketStrategies; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding.FORWARDING_MIME_TYPE; - -/** - * @author Spencer Gibb - */ -public class GatewayRSocketTests { - - private static Log logger = LogFactory.getLog(GatewayRSocketTests.class); - - private RoutingTable routingTable; - - private Payload incomingPayload; - - private final RSocketStrategies rSocketStrategies = RSocketStrategies.builder() - .decoder(new Forwarding.Decoder()).encoder(new Forwarding.Encoder()).build(); - - private DefaultMetadataExtractor metadataExtractor = new DefaultMetadataExtractor( - rSocketStrategies.decoders()); - - // TODO: add tests for metrics and other request types - - @Before - public void init() { - routingTable = mock(RoutingTable.class); - - this.metadataExtractor.metadataToExtract(FORWARDING_MIME_TYPE, Forwarding.class, - "forwarding"); - - MetadataEncoder encoder = new MetadataEncoder(Metadata.COMPOSITE_MIME_TYPE, - this.rSocketStrategies); - Forwarding metadata = Forwarding.of(1).with(WellKnownKey.SERVICE_NAME, "mock") - .build(); - DataBuffer dataBuffer = encoder.metadata(metadata, FORWARDING_MIME_TYPE).encode(); - DataBuffer data = MetadataEncoder.emptyDataBuffer(rSocketStrategies); - incomingPayload = PayloadUtils.createPayload(data, dataBuffer); - - RSocket rSocket = mock(RSocket.class); - Tuple2 tuple = Tuples.of("1111", rSocket); - when(routingTable.findRSockets(any(TagsMetadata.class))) - .thenReturn(Collections.singletonList(tuple)); - - when(rSocket.requestResponse(any(Payload.class))) - .thenReturn(Mono.just(DefaultPayload.create("response"))); - } - - @Test - public void multipleFilters() { - TestFilter filter1 = new TestFilter(); - TestFilter filter2 = new TestFilter(); - TestFilter filter3 = new TestFilter(); - - Payload payload = new TestGatewayRSocket(routingTable, - new TestRoutes(filter1, filter2, filter3), metadataExtractor) - .requestResponse(incomingPayload).block(Duration.ZERO); - - assertThat(filter1.invoked()).isTrue(); - assertThat(filter2.invoked()).isTrue(); - assertThat(filter3.invoked()).isTrue(); - assertThat(payload).isNotNull(); - } - - @Test - public void zeroFilters() { - Payload payload = new TestGatewayRSocket(routingTable, new TestRoutes(), - metadataExtractor).requestResponse(incomingPayload).block(Duration.ZERO); - - assertThat(payload).isNotNull(); - } - - @Test - public void shortcircuitFilter() { - - TestFilter filter1 = new TestFilter(); - ShortcircuitingFilter filter2 = new ShortcircuitingFilter(); - TestFilter filter3 = new TestFilter(); - - TestGatewayRSocket gatewayRSocket = new TestGatewayRSocket(routingTable, - new TestRoutes(filter1, filter2, filter3), metadataExtractor); - Mono response = gatewayRSocket.requestResponse(incomingPayload); - - // a false filter will create a pending rsocket that blocks forever - // this tweaks the rsocket to complete. - gatewayRSocket.getProcessor().onNext(null); - - StepVerifier.withVirtualTime(() -> response).expectSubscription() - .verifyComplete(); - - assertThat(filter1.invoked()).isTrue(); - assertThat(filter2.invoked()).isTrue(); - assertThat(filter3.invoked()).isFalse(); - } - - @Test - public void asyncFilter() { - - AsyncFilter filter = new AsyncFilter(); - - Payload payload = new TestGatewayRSocket(routingTable, new TestRoutes(filter), - metadataExtractor).requestResponse(incomingPayload) - .block(Duration.ofSeconds(5)); - - assertThat(filter.invoked()).isTrue(); - assertThat(payload).isNotNull(); - } - - // TODO: add exception handlers? - @Test(expected = IllegalStateException.class) - public void handleErrorFromFilter() { - - ExceptionFilter filter = new ExceptionFilter(); - - new TestGatewayRSocket(routingTable, new TestRoutes(filter), metadataExtractor) - .requestResponse(incomingPayload).block(Duration.ofSeconds(5)); - - // assertNull(socket); - } - - private static RouteSetup getMetadata() { - return RouteSetup.of(1L, "service").build(); - } - - private static class TestGatewayRSocket extends GatewayRSocket { - - TestGatewayRSocket(RoutingTable routingTable, Routes routes, - MetadataExtractor metadataExtractor) { - super(routes, new TestPendingFactory(routingTable, routes, metadataExtractor), - new LoadBalancerFactory(routingTable), new SimpleMeterRegistry(), - new BrokerProperties(), metadataExtractor, getMetadata()); - } - - private MonoProcessor getProcessor() { - TestPendingFactory factory = (TestPendingFactory) super.getPendingFactory(); - return factory.processor; - } - - } - - private static class TestPendingFactory extends PendingRequestRSocketFactory { - - private final MonoProcessor processor = MonoProcessor.create(); - - private final MetadataExtractor metadataExtractor; - - TestPendingFactory(RoutingTable routingTable, Routes routes, - MetadataExtractor metadataExtractor) { - super(routingTable, routes, metadataExtractor); - this.metadataExtractor = metadataExtractor; - } - - @Override - protected PendingRequestRSocket constructPendingRSocket( - GatewayExchange exchange) { - Function> routeFinder = registeredEvent -> getRouteMono( - registeredEvent, exchange); - return new PendingRequestRSocket(metadataExtractor, routeFinder, - tagsMetadata -> { - Tags tags = exchange.getTags().and("responder.id", - tagsMetadata.getRouteId()); - exchange.setTags(tags); - }, processor); - } - - } - - private static class TestRoutes implements Routes { - - private final Route route; - - private List filters; - - TestRoutes() { - this(Collections.emptyList()); - } - - TestRoutes(GatewayFilter... filters) { - this(Arrays.asList(filters)); - } - - TestRoutes(List filters) { - this.filters = filters; - route = DefaultRoute.builder().id("route1") - .routingMetadata(RouteSetup.of(1L, "mock").build()) - .predicate(exchange -> Mono.just(true)).filters(filters).build(); - } - - @Override - public Flux getRoutes() { - return Flux.just(route); - } - - } - - private static class TestFilter implements GatewayFilter { - - private volatile boolean invoked; - - public boolean invoked() { - return this.invoked; - } - - @Override - public Mono filter(GatewayExchange exchange, GatewayFilterChain chain) { - this.invoked = true; - return doFilter(exchange, chain); - } - - public Mono doFilter(GatewayExchange exchange, - GatewayFilterChain chain) { - return chain.filter(exchange); - } - - } - - private static class ShortcircuitingFilter extends TestFilter { - - @Override - public Mono doFilter(GatewayExchange exchange, - GatewayFilterChain chain) { - return Mono.empty(); - } - - } - - private static class AsyncFilter extends TestFilter { - - @Override - public Mono doFilter(GatewayExchange exchange, - GatewayFilterChain chain) { - return doAsyncWork().flatMap(asyncResult -> { - logger.debug("Async result: " + asyncResult); - return chain.filter(exchange); - }); - } - - private Mono doAsyncWork() { - return Mono.delay(Duration.ofMillis(100L)).map(l -> "123"); - } - - } - - private static class ExceptionFilter implements GatewayFilter { - - @Override - public Mono filter(GatewayExchange exchange, GatewayFilterChain chain) { - return Mono.error(new IllegalStateException("boo")); - } - - } - - /* - * private static class TestExceptionHandler implements WebExceptionHandler { - * - * private Throwable ex; - * - * @Override public Mono handle(GatewayExchange exchange, Throwable ex) { - * this.ex = ex; return Mono.error(ex); } } - */ - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableRoutesTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableRoutesTests.java deleted file mode 100644 index 1ca106d1..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableRoutesTests.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.routing; - -import java.util.HashSet; - -import io.rsocket.RSocket; -import org.junit.Test; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.core.GatewayExchange; -import org.springframework.cloud.gateway.rsocket.route.Route; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable.RegisteredEvent; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable.RouteEntry; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.cloud.gateway.rsocket.core.GatewayExchange.Type.REQUEST_RESPONSE; - -public class RoutingTableRoutesTests { - - @Test - public void routesAreBuilt() { - RoutingTable routingTable = mock(RoutingTable.class); - RoutingTableRoutes routes = new RoutingTableRoutes(routingTable); - - HashSet routeIds = new HashSet<>(); - routeIds.add("2"); - when(routingTable.findRouteIds(any(TagsMetadata.class))).thenReturn(routeIds); - addRoute(routes, "1"); - addRoute(routes, "2"); - addRoute(routes, "3"); - - Forwarding forwarding = Forwarding.of(1L).routeId("2").build(); - Mono routeMono = routes - .findRoute(new GatewayExchange(REQUEST_RESPONSE, forwarding)); - - StepVerifier.create(routeMono).consumeNextWith(route -> { - assertThat(route).isNotNull().extracting(Route::getId).isEqualTo("2"); - }).verifyComplete(); - } - - void addRoute(RoutingTableRoutes routes, String routeId) { - TagsMetadata tagsMetadata = TagsMetadata.builder().routeId(routeId).build(); - - RSocket rsocket = mock(RSocket.class); - routes.accept(new RegisteredEvent(new RouteEntry(rsocket, tagsMetadata))); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableTests.java deleted file mode 100644 index a80a7b84..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/routing/RoutingTableTests.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.routing; - -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -import io.rsocket.AbstractRSocket; -import io.rsocket.RSocket; -import org.junit.Test; -import org.roaringbitmap.RoaringBitmap; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey; -import org.springframework.core.style.ToStringCreator; - -import static org.assertj.core.api.Assertions.assertThat; - -public class RoutingTableTests { - - @Test - public void testIndexesCreatedAndSearchWorks() { - RoutingTable routingTable = new RoutingTable(); - // @formatter:off - TagsMetadata setupTags1 = TagsMetadata.builder() - .with(WellKnownKey.ROUTE_ID, "1111") - .with(WellKnownKey.SERVICE_NAME, "serviceA") - .with(WellKnownKey.CLUSTER_NAME, "clusterA") - .build(); - TagsMetadata setupTags2 = TagsMetadata.builder() - .with(WellKnownKey.ROUTE_ID, "2222") - .with(WellKnownKey.SERVICE_NAME, "serviceA") - .with(WellKnownKey.CLUSTER_NAME, "clusterB") - .build(); - TagsMetadata setupTags3 = TagsMetadata.builder() - .with(WellKnownKey.ROUTE_ID, "3333") - .with(WellKnownKey.SERVICE_NAME, "serviceB") - .with(WellKnownKey.REGION, "region1") - .build(); - TagsMetadata setupTags4 = TagsMetadata.builder() - .with(WellKnownKey.ROUTE_ID, "4444") - .with(WellKnownKey.SERVICE_NAME, "serviceB") - .with(WellKnownKey.CLUSTER_NAME, "clusterB") - .with(WellKnownKey.ZONE, "zone1") - .build(); - TagsMetadata setupTags5 = TagsMetadata.builder() - .with(WellKnownKey.ROUTE_ID, "5555") - .with(WellKnownKey.SERVICE_NAME, "serviceA") - .with(WellKnownKey.CLUSTER_NAME, "clusterB") - .build(); - // @formatter:on - - AtomicInteger internalRouteId = routingTable.internalRouteId; - RSocket rSocket1 = assertRegister(routingTable, setupTags1, - internalRouteId.get() + 1); - internalRouteId.set(99); - RSocket rSocket2 = assertRegister(routingTable, setupTags2, - internalRouteId.get() + 1); - internalRouteId.set(999); - RSocket rSocket3 = assertRegister(routingTable, setupTags3, - internalRouteId.get() + 1); - internalRouteId.set(9999); - RSocket rSocket4 = assertRegister(routingTable, setupTags4, - internalRouteId.get() + 1); - internalRouteId.set(99999); - RSocket rSocket5 = assertRegister(routingTable, setupTags5, - internalRouteId.get() + 1); - - // @formatter:off - TagsMetadata searchTags1 = TagsMetadata.builder() - .with(WellKnownKey.SERVICE_NAME, "serviceA") - .with(WellKnownKey.CLUSTER_NAME, "clusterB") - .build(); - // @formatter:on - - List> results1 = routingTable.findRSockets(searchTags1); - assertThat(results1).containsOnly(Tuples.of("2222", rSocket2), - Tuples.of("5555", rSocket5)); - - // @formatter:off - TagsMetadata searchTags2 = TagsMetadata.builder() - .with(WellKnownKey.ROUTE_ID, "3333") - .build(); - // @formatter:on - - List> results2 = routingTable.findRSockets(searchTags2); - assertThat(results2).containsOnly(Tuples.of("3333", rSocket3)); - - // @formatter:off - TagsMetadata searchTags3 = TagsMetadata.builder() - .with(WellKnownKey.ZONE, "zone1") - .with(WellKnownKey.SERVICE_NAME, "serviceB") - .with(WellKnownKey.CLUSTER_NAME, "clusterB") - .build(); - // @formatter:on - - List> results3 = routingTable.findRSockets(searchTags3); - assertThat(results3).containsOnly(Tuples.of("4444", rSocket4)); - - assertDeregister(routingTable, setupTags1); - assertDeregister(routingTable, setupTags2); - assertDeregister(routingTable, setupTags3); - assertDeregister(routingTable, setupTags4); - assertDeregister(routingTable, setupTags5); - assertThat(routingTable.deregister(setupTags5)).isFalse(); - } - - void assertDeregister(RoutingTable routingTable, TagsMetadata tagsMetadata) { - boolean result = routingTable.deregister(tagsMetadata); - assertThat(result).isTrue(); - String routeId = tagsMetadata.getRouteId(); - assertThat(routingTable.internalRouteIdToRouteId).doesNotContainValue(routeId); - assertThat(routingTable.routeEntries).doesNotContainKey(routeId); - } - - private RSocket assertRegister(RoutingTable routingTable, TagsMetadata tagsMetadata, - int internalId) { - String routeId = tagsMetadata.getRouteId(); - RSocket rsocket = new TestRSocket(routeId); - routingTable.register(tagsMetadata, rsocket); - - assertThat(routingTable.internalRouteId).hasValue(internalId); - assertThat(routingTable.internalRouteIdToRouteId).containsEntry(internalId, - routeId); - assertThat(routingTable.routeEntries).containsKey(routeId); - tagsMetadata.getTags().forEach((key, value) -> { - RoutingTable.TagKey tagKey = new RoutingTable.TagKey(key, value); - assertThat(routingTable.tagsToBitmaps).containsKey(tagKey); - RoaringBitmap bitmap = routingTable.tagsToBitmaps.get(tagKey); - assertThat(bitmap.contains(internalId)); - }); - - return rsocket; - } - - static class TestRSocket extends AbstractRSocket { - - final String routeId; - - TestRSocket(String routeId) { - this.routeId = routeId; - } - - @Override - public String toString() { - return new ToStringCreator(this).append("routeId", routeId).toString(); - - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/socketacceptor/GatewaySocketAcceptorTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/socketacceptor/GatewaySocketAcceptorTests.java deleted file mode 100644 index 79cc7787..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/socketacceptor/GatewaySocketAcceptorTests.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.socketacceptor; - -import java.time.Duration; -import java.util.Arrays; -import java.util.Collections; - -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.simple.SimpleMeterRegistry; -import io.rsocket.ConnectionSetupPayload; -import io.rsocket.Payload; -import io.rsocket.RSocket; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Before; -import org.junit.Test; -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.autoconfigure.BrokerProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.Metadata; -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.common.test.MetadataEncoder; -import org.springframework.cloud.gateway.rsocket.core.GatewayRSocket; -import org.springframework.cloud.gateway.rsocket.core.GatewayRSocketFactory; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.messaging.rsocket.DefaultMetadataExtractor; -import org.springframework.messaging.rsocket.PayloadUtils; -import org.springframework.messaging.rsocket.RSocketStrategies; - -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup.ROUTE_SETUP_MIME_TYPE; - -/** - * @author Spencer Gibb - */ -public class GatewaySocketAcceptorTests { - - private static Log logger = LogFactory.getLog(GatewaySocketAcceptorTests.class); - - private GatewayRSocketFactory factory; - - private ConnectionSetupPayload setupPayload; - - private RSocket sendingSocket; - - private MeterRegistry meterRegistry; - - private BrokerProperties properties = new BrokerProperties(); - - private final RSocketStrategies rSocketStrategies = RSocketStrategies.builder() - .decoder(new RouteSetup.Decoder()).encoder(new RouteSetup.Encoder()).build(); - - private DefaultMetadataExtractor metadataExtractor = new DefaultMetadataExtractor( - rSocketStrategies.decoders()); - - @Before - public void init() { - this.factory = mock(GatewayRSocketFactory.class); - this.setupPayload = mock(ConnectionSetupPayload.class); - this.sendingSocket = mock(RSocket.class); - this.meterRegistry = new SimpleMeterRegistry(); - - this.metadataExtractor.metadataToExtract(ROUTE_SETUP_MIME_TYPE, RouteSetup.class, - "routesetup"); - - when(this.factory.create(any(TagsMetadata.class))) - .thenReturn(mock(GatewayRSocket.class)); - - when(this.setupPayload.metadataMimeType()) - .thenReturn(Metadata.COMPOSITE_MIME_TYPE.toString()); - - when(this.setupPayload.hasMetadata()).thenReturn(true); - - MetadataEncoder encoder = new MetadataEncoder(Metadata.COMPOSITE_MIME_TYPE, - this.rSocketStrategies); - encoder.metadata(RouteSetup.of(1L, "myservice").build(), ROUTE_SETUP_MIME_TYPE); - DataBuffer dataBuffer = encoder.encode(); - DataBuffer data = MetadataEncoder.emptyDataBuffer(rSocketStrategies); - Payload payload = PayloadUtils.createPayload(data, dataBuffer); - when(setupPayload.metadata()).thenReturn(payload.metadata()); - } - - // TODO: test metrics - - @Test - public void multipleFilters() { - TestFilter filter1 = new TestFilter(); - TestFilter filter2 = new TestFilter(); - TestFilter filter3 = new TestFilter(); - - RSocket socket = new GatewaySocketAcceptor(this.factory, - Arrays.asList(filter1, filter2, filter3), this.meterRegistry, - this.properties, this.metadataExtractor) - .accept(this.setupPayload, this.sendingSocket) - .block(Duration.ZERO); - - assertThat(filter1.invoked()).isTrue(); - assertThat(filter2.invoked()).isTrue(); - assertThat(filter3.invoked()).isTrue(); - assertThat(socket).isNotNull(); - } - - @Test - public void zeroFilters() { - RSocket socket = new GatewaySocketAcceptor(this.factory, Collections.emptyList(), - this.meterRegistry, this.properties, this.metadataExtractor) - .accept(this.setupPayload, this.sendingSocket) - .block(Duration.ZERO); - - assertThat(socket).isNotNull(); - } - - @Test - public void shortcircuitFilter() { - - TestFilter filter1 = new TestFilter(); - ShortcircuitingFilter filter2 = new ShortcircuitingFilter(); - TestFilter filter3 = new TestFilter(); - - RSocket socket = new GatewaySocketAcceptor(this.factory, - Arrays.asList(filter1, filter2, filter3), this.meterRegistry, - this.properties, this.metadataExtractor) - .accept(this.setupPayload, this.sendingSocket) - .block(Duration.ZERO); - - assertThat(filter1.invoked()).isTrue(); - assertThat(filter2.invoked()).isTrue(); - assertThat(filter3.invoked()).isFalse(); - assertThat(socket).isNull(); - } - - @Test - public void asyncFilter() { - - AsyncFilter filter = new AsyncFilter(); - - RSocket socket = new GatewaySocketAcceptor(this.factory, singletonList(filter), - this.meterRegistry, this.properties, this.metadataExtractor) - .accept(this.setupPayload, this.sendingSocket) - .block(Duration.ofSeconds(5)); - - assertThat(filter.invoked()).isTrue(); - assertThat(socket).isNotNull(); - } - - // TODO: add exception handlers? - @Test(expected = IllegalStateException.class) - public void handleErrorFromFilter() { - - ExceptionFilter filter = new ExceptionFilter(); - - new GatewaySocketAcceptor(this.factory, singletonList(filter), this.meterRegistry, - this.properties, this.metadataExtractor) - .accept(this.setupPayload, this.sendingSocket) - .block(Duration.ofSeconds(5)); - - } - - private static class TestFilter implements SocketAcceptorFilter { - - private volatile boolean invoked; - - public boolean invoked() { - return this.invoked; - } - - @Override - public Mono filter(SocketAcceptorExchange exchange, - SocketAcceptorFilterChain chain) { - this.invoked = true; - return doFilter(exchange, chain); - } - - public Mono doFilter(SocketAcceptorExchange exchange, - SocketAcceptorFilterChain chain) { - return chain.filter(exchange); - } - - } - - private static class ShortcircuitingFilter extends TestFilter { - - @Override - public Mono doFilter(SocketAcceptorExchange exchange, - SocketAcceptorFilterChain chain) { - return Mono.empty(); - } - - } - - private static class AsyncFilter extends TestFilter { - - @Override - public Mono doFilter(SocketAcceptorExchange exchange, - SocketAcceptorFilterChain chain) { - return doAsyncWork().flatMap(asyncResult -> { - logger.debug("Async result: " + asyncResult); - return chain.filter(exchange); - }); - } - - private Mono doAsyncWork() { - return Mono.delay(Duration.ofMillis(100L)).map(l -> "123"); - } - - } - - private static class ExceptionFilter implements SocketAcceptorFilter { - - @Override - public Mono filter(SocketAcceptorExchange exchange, - SocketAcceptorFilterChain chain) { - return Mono.error(new IllegalStateException("boo")); - } - - } - - /* - * private static class TestExceptionHandler implements WebExceptionHandler { - * - * private Throwable ex; - * - * @Override public Mono handle(SocketAcceptorExchange exchange, Throwable ex) { - * this.ex = ex; return Mono.error(ex); } } - */ - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicateFilterTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicateFilterTests.java deleted file mode 100644 index 127aafe9..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/socketacceptor/SocketAcceptorPredicateFilterTests.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.socketacceptor; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import io.rsocket.ConnectionSetupPayload; -import io.rsocket.RSocket; -import org.junit.Test; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import org.springframework.cloud.gateway.rsocket.filter.RSocketFilter.Success; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -public class SocketAcceptorPredicateFilterTests { - - @Test - public void noPredicateWorks() { - Mono result = runFilter(Collections.emptyList()); - StepVerifier.create(result).expectNext(Success.INSTANCE).verifyComplete(); - } - - @Test - public void singleTruePredicateWorks() { - TestPredicate predicate = new TestPredicate(true); - Mono result = runFilter(predicate); - StepVerifier.create(result).expectNext(Success.INSTANCE).verifyComplete(); - assertThat(predicate.invoked()).isTrue(); - } - - @Test - public void singleFalsePredicateWorks() { - TestPredicate predicate = new TestPredicate(false); - Mono result = runFilter(predicate); - StepVerifier.create(result).verifyComplete(); - - assertThat(predicate.invoked()).isTrue(); - } - - @Test - public void multipleFalsePredicateWorks() { - TestPredicate predicate = new TestPredicate(false); - TestPredicate predicate2 = new TestPredicate(false); - Mono result = runFilter(predicate, predicate2); - StepVerifier.create(result).verifyComplete(); - - assertThat(predicate.invoked()).isTrue(); - assertThat(predicate2.invoked()).isTrue(); // Async predicates don't short circuit - } - - @Test - public void multiplePredicatesNoSuccessWorks() { - TestPredicate truePredicate = new TestPredicate(true); - TestPredicate falsePredicate = new TestPredicate(false); - Mono result = runFilter(truePredicate, falsePredicate); - StepVerifier.create(result).verifyComplete(); - assertThat(truePredicate.invoked()).isTrue(); - assertThat(falsePredicate.invoked()).isTrue(); - } - - @Test - public void multiplePredicatesSuccessWorks() { - TestPredicate truePredicate = new TestPredicate(true); - TestPredicate truePredicate2 = new TestPredicate(true); - Mono result = runFilter(truePredicate, truePredicate2); - StepVerifier.create(result).expectNext(Success.INSTANCE).verifyComplete(); - assertThat(truePredicate.invoked()).isTrue(); - assertThat(truePredicate2.invoked()).isTrue(); - } - - private Mono runFilter(SocketAcceptorPredicate predicate) { - return runFilter(Collections.singletonList(predicate)); - } - - private Mono runFilter(SocketAcceptorPredicate... predicates) { - return runFilter(Arrays.asList(predicates)); - } - - private Mono runFilter(List predicates) { - SocketAcceptorPredicateFilter filter = new SocketAcceptorPredicateFilter( - predicates); - SocketAcceptorExchange exchange = new SocketAcceptorExchange( - mock(ConnectionSetupPayload.class), mock(RSocket.class)); - SocketAcceptorFilterChain filterChain = new SocketAcceptorFilterChain( - Collections.singletonList(filter)); - return filter.filter(exchange, filterChain); - } - - private class TestPredicate implements SocketAcceptorPredicate { - - private boolean invoked = false; - - private final Mono test; - - TestPredicate(boolean value) { - test = Mono.just(value); - } - - @Override - public Publisher apply(SocketAcceptorExchange exchange) { - invoked = true; - return test; - } - - public boolean invoked() { - return invoked; - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/test/PingPongApp.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/test/PingPongApp.java deleted file mode 100644 index 0546226d..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/test/PingPongApp.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.test; - -import java.time.Duration; -import java.util.LinkedHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tag; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.ByteBufUtil; -import io.rsocket.Payload; -import io.rsocket.RSocket; -import io.rsocket.RSocketFactory; -import io.rsocket.frame.decoder.PayloadDecoder; -import io.rsocket.micrometer.MicrometerRSocketInterceptor; -import io.rsocket.transport.netty.client.TcpClientTransport; -import io.rsocket.util.DefaultPayload; -import io.rsocket.util.RSocketProxy; -import lombok.extern.slf4j.Slf4j; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Hooks; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata; -import org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey; -import org.springframework.cloud.gateway.rsocket.common.test.MetadataEncoder; -import org.springframework.cloud.gateway.rsocket.core.GatewayExchange; -import org.springframework.cloud.gateway.rsocket.core.GatewayFilter; -import org.springframework.cloud.gateway.rsocket.core.GatewayFilterChain; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorExchange; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorFilter; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorFilterChain; -import org.springframework.context.ApplicationListener; -import org.springframework.context.annotation.Bean; -import org.springframework.core.Ordered; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.messaging.rsocket.RSocketStrategies; - -import static io.netty.buffer.Unpooled.EMPTY_BUFFER; -import static org.springframework.cloud.gateway.rsocket.common.metadata.Metadata.COMPOSITE_MIME_TYPE; -import static org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup.ROUTE_SETUP_MIME_TYPE; - -@SpringBootApplication -public class PingPongApp { - - @Bean - public Ping ping1() { - return new Ping(1L); - } - - @Bean - @ConditionalOnProperty("ping.two.enabled") - public Ping ping2() { - return new Ping(2L); - } - - @Bean - public Pong pong() { - return new Pong(); - } - - @Bean - public MySocketAcceptorFilter mySocketAcceptorFilter() { - return new MySocketAcceptorFilter(); - } - - public static void main(String[] args) { - Hooks.onOperatorDebug(); - SpringApplication.run(PingPongApp.class, args); - } - - static String reply(String in) { - if (in.length() > 4) { - in = in.substring(0, 4); - } - switch (in.toLowerCase()) { - case "ping": - return "pong"; - case "pong": - return "ping"; - default: - throw new IllegalArgumentException("Value must be ping or pong, not " + in); - } - } - - static ByteBuf getRouteSetupMetadata(RSocketStrategies strategies, String name, - long id) { - RouteSetup routeSetup = RouteSetup.of(id, name) - .with("current-time", String.valueOf(System.currentTimeMillis())).build(); - LinkedHashMap tags = new LinkedHashMap<>(); - tags.put(new TagsMetadata.Key(WellKnownKey.TIME_ZONE), - System.currentTimeMillis() + ""); - DataBuffer dataBuffer = new MetadataEncoder(COMPOSITE_MIME_TYPE, strategies) - .metadata(routeSetup, ROUTE_SETUP_MIME_TYPE).encode(); - return TagsMetadata.asByteBuf(dataBuffer); - } - - static ByteBuf getForwardingMetadata(RSocketStrategies strategies, String name, - long id) { - Forwarding metadata = Forwarding.of(id).serviceName(name).build(); - DataBuffer dataBuffer = new MetadataEncoder(COMPOSITE_MIME_TYPE, strategies) - .metadata(metadata, Forwarding.FORWARDING_MIME_TYPE).encode(); - return TagsMetadata.asByteBuf(dataBuffer); - } - - @Slf4j - public static class Ping - implements Ordered, ApplicationListener { - - @Autowired - private MeterRegistry meterRegistry; - - @Autowired - private RSocketStrategies strategies; - - private final Long id; - - private final AtomicInteger pongsReceived = new AtomicInteger(); - - private Flux pongFlux; - - public Ping(Long id) { - this.id = id; - } - - @Override - public int getOrder() { - return 0; - } - - @Override - public void onApplicationEvent(ApplicationReadyEvent event) { - log.info("Starting Ping" + id); - ConfigurableEnvironment env = event.getApplicationContext().getEnvironment(); - Integer take = env.getProperty("ping.take", Integer.class, null); - Integer gatewayPort = env.getProperty("spring.rsocket.server.port", - Integer.class, 7002); - - log.debug("ping.take: " + take); - - MicrometerRSocketInterceptor interceptor = new MicrometerRSocketInterceptor( - meterRegistry, Tag.of("component", "ping")); - ByteBuf metadata = getRouteSetupMetadata(strategies, "ping", id); - Payload setupPayload = DefaultPayload.create(EMPTY_BUFFER, metadata); - - pongFlux = RSocketFactory.connect().frameDecoder(PayloadDecoder.ZERO_COPY) - .metadataMimeType(COMPOSITE_MIME_TYPE.toString()) - .setupPayload(setupPayload).addRequesterPlugin(interceptor) - .transport(TcpClientTransport.create(gatewayPort)) // proxy - .start().log("startPing" + id) - .flatMapMany(socket -> doPing(take, socket)).cast(String.class) - .doOnSubscribe(o -> { - if (log.isDebugEnabled()) { - log.debug("ping doOnSubscribe"); - } - }); - - boolean subscribe = env.getProperty("ping.subscribe", Boolean.class, true); - - if (subscribe) { - pongFlux.subscribe(); - } - } - - Publisher doPing(Integer take, RSocket socket) { - Flux pong = socket - .requestChannel(Flux.interval(Duration.ofSeconds(1)).map(i -> { - ByteBuf data = ByteBufUtil.writeUtf8(ByteBufAllocator.DEFAULT, - "ping" + id); - ByteBuf routingMetadata = getForwardingMetadata(strategies, - "pong", id); - log.debug("Sending ping" + id); - return DefaultPayload.create(data, routingMetadata); - // onBackpressure is needed in case pong is not available yet - }).log("doPing") - .onBackpressureDrop(payload -> log - .debug("Dropped payload " + payload.getDataUtf8()))) - .map(Payload::getDataUtf8).doOnNext(str -> { - int received = pongsReceived.incrementAndGet(); - log.info("received " + str + "(" + received + ") in Ping" + id); - }).doFinally(signal -> socket.dispose()); - if (take != null) { - return pong.take(take); - } - return pong; - } - - public Flux getPongFlux() { - return pongFlux; - } - - public int getPongsReceived() { - return pongsReceived.get(); - } - - } - - @Slf4j - public static class Pong - implements Ordered, ApplicationListener { - - @Autowired - private MeterRegistry meterRegistry; - - @Autowired - private RSocketStrategies strategies; - - private final AtomicInteger pingsReceived = new AtomicInteger(); - - @Override - public int getOrder() { - return 1; - } - - @Override - public void onApplicationEvent(ApplicationReadyEvent event) { - ConfigurableEnvironment env = event.getApplicationContext().getEnvironment(); - Integer pongDelay = env.getProperty("pong.delay", Integer.class, 5000); - try { - Thread.sleep(pongDelay); - } - catch (InterruptedException e) { - e.printStackTrace(); - } - log.info("Starting Pong"); - Integer gatewayPort = env.getProperty("spring.rsocket.server.port", - Integer.class, 7002); - MicrometerRSocketInterceptor interceptor = new MicrometerRSocketInterceptor( - meterRegistry, Tag.of("component", "pong")); - - ByteBuf announcementMetadata = getRouteSetupMetadata(strategies, "pong", 3L); - RSocketFactory.connect().metadataMimeType(COMPOSITE_MIME_TYPE.toString()) - .setupPayload( - DefaultPayload.create(EMPTY_BUFFER, announcementMetadata)) - .addRequesterPlugin(interceptor).acceptor(this::accept) - .transport(TcpClientTransport.create(gatewayPort)) // proxy - .start().block(); - } - - @SuppressWarnings("Duplicates") - RSocket accept(RSocket rSocket) { - RSocket pong = new RSocketProxy(rSocket) { - - @Override - public Flux requestChannel(Publisher payloads) { - return Flux.from(payloads).map(Payload::getDataUtf8).doOnNext(str -> { - int received = pingsReceived.incrementAndGet(); - log.info("received " + str + "(" + received + ") in Pong"); - }).map(PingPongApp::reply).map(reply -> { - ByteBuf data = ByteBufUtil.writeUtf8(ByteBufAllocator.DEFAULT, - reply); - ByteBuf routingMetadata = getForwardingMetadata(strategies, - "ping", 1L); - return DefaultPayload.create(data, routingMetadata); - }); - } - }; - return pong; - } - - public int getPingsReceived() { - return pingsReceived.get(); - } - - } - - @Slf4j - public static class MyGatewayFilter implements GatewayFilter { - - private AtomicBoolean invoked = new AtomicBoolean(false); - - @Override - public Mono filter(GatewayExchange exchange, GatewayFilterChain chain) { - log.info("in custom gateway filter"); - invoked.compareAndSet(false, true); - return chain.filter(exchange); - } - - public boolean invoked() { - return invoked.get(); - } - - } - - @Slf4j - public static class MySocketAcceptorFilter implements SocketAcceptorFilter, Ordered { - - private AtomicBoolean invoked = new AtomicBoolean(false); - - @Override - public Mono filter(SocketAcceptorExchange exchange, - SocketAcceptorFilterChain chain) { - log.info("in custom socket acceptor filter"); - invoked.compareAndSet(false, true); - return chain.filter(exchange); - } - - @Override - public int getOrder() { - return 0; - } - - public boolean invoked() { - return invoked.get(); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/test/SocketAcceptorFilterOrderTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/test/SocketAcceptorFilterOrderTests.java deleted file mode 100644 index 1affc4be..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/java/org/springframework/cloud/gateway/rsocket/test/SocketAcceptorFilterOrderTests.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2018-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.Test; - -import org.springframework.cloud.gateway.rsocket.routing.RoutingTable; -import org.springframework.cloud.gateway.rsocket.routing.RoutingTableSocketAcceptorFilter; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorFilter; -import org.springframework.cloud.gateway.rsocket.socketacceptor.SocketAcceptorPredicateFilter; -import org.springframework.core.OrderComparator; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -public class SocketAcceptorFilterOrderTests { - - @Test - public void predicateFilterAfterRegistryFilter() { - SocketAcceptorFilter predicateFilter = new SocketAcceptorPredicateFilter( - Collections.emptyList()); - SocketAcceptorFilter registryFilter = new RoutingTableSocketAcceptorFilter( - mock(RoutingTable.class)); - List filters = Arrays.asList(predicateFilter, - registryFilter); - OrderComparator.sort(filters); - - assertThat(filters).containsExactly(registryFilter, predicateFilter); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/resources/application.yml b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/resources/application.yml deleted file mode 100644 index bf3bf7d1..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-broker/src/test/resources/application.yml +++ /dev/null @@ -1,17 +0,0 @@ - -logging: - level: - # org.springframework.cloud.gateway.rsocket: DEBUG - org.springframework.cloud.gateway.rsocket: TRACE - org.springframework.messaging.handler.invocation.reactive: TRACE - -management: - endpoints: - web: - exposure: - include: '*' -spring: - cloud: - gateway: - rsocket: - route-id: 1234 diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/pom.xml b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/pom.xml deleted file mode 100644 index 36860a83..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/pom.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - - - 4.0.0 - - org.springframework.cloud - spring-cloud-gateway-rsocket - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-gateway-rsocket-client - Spring Cloud Gateway RSocket Client - Spring Cloud Gateway RSocket Client - - - - org.springframework.boot - spring-boot-starter-validation - - - org.springframework.boot - spring-boot-starter-rsocket - - - org.springframework.cloud - spring-cloud-gateway-rsocket-common - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.boot - spring-boot-starter-actuator - test - - - org.projectlombok - lombok - test - - - org.springframework.boot - spring-boot-starter-test - test - - - io.projectreactor - reactor-test - test - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - -parameters - - - - - - default-compile - none - - - - default-testCompile - none - - - java-compile - compile - - compile - - - - java-test-compile - test-compile - - testCompile - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.1.0 - - - - test-jar - - - - - - - - - java8plus - - [1.8,2.0) - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - -parameters - - - - - - - - - diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/BrokerClient.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/BrokerClient.java deleted file mode 100644 index a16b631f..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/BrokerClient.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.client; - -import java.util.function.Consumer; - -import reactor.core.publisher.Mono; - -import org.springframework.cloud.gateway.rsocket.common.autoconfigure.Broker; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.messaging.rsocket.RSocketRequester; - -public class BrokerClient { - - private final ClientProperties properties; - - private final RSocketRequester.Builder builder; - - public BrokerClient(ClientProperties properties, RSocketRequester.Builder builder) { - this.properties = properties; - this.builder = builder; - } - - public ClientProperties getProperties() { - return this.properties; - } - - public RSocketRequester.Builder getRSocketRequesterBuilder() { - return this.builder; - } - - public Mono connect() { - return connect(builder); - } - - public Mono connect(RSocketRequester.Builder requesterBuilder) { - Broker broker = properties.getBroker(); - switch (broker.getConnectionType()) { - case WEBSOCKET: - return requesterBuilder.connectWebSocket(broker.getWsUri()); - } - return requesterBuilder.connectTcp(broker.getHost(), broker.getPort()); - } - - public Consumer> forwarding(String destServiceName) { - return spec -> { - Forwarding forwarding = Forwarding.of(properties.getRouteId()) - .serviceName(destServiceName).build(); - spec.metadata(forwarding, Forwarding.FORWARDING_MIME_TYPE); - }; - } - - public Consumer> forwarding( - Consumer builderConsumer) { - return spec -> { - Forwarding.Builder builder = Forwarding.of(properties.getRouteId()); - builderConsumer.accept(builder); - spec.metadata(builder.build(), Forwarding.FORWARDING_MIME_TYPE); - }; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/BrokerClientConnectionListener.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/BrokerClientConnectionListener.java deleted file mode 100644 index 41ca368e..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/BrokerClientConnectionListener.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.client; - -import java.util.function.Consumer; - -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.ApplicationListener; -import org.springframework.context.PayloadApplicationEvent; -import org.springframework.core.Ordered; -import org.springframework.core.ResolvableType; -import org.springframework.messaging.rsocket.RSocketRequester; - -/** - * Automatically subscribes to {@link BrokerClient}. On subscribe it publishes a - * {@link PayloadApplicationEvent} with a generic type of {@link RSocketRequester}. - */ -public class BrokerClientConnectionListener - implements ApplicationListener, Ordered { - - private final BrokerClient brokerClient; - - private final ApplicationEventPublisher publisher; - - public BrokerClientConnectionListener(BrokerClient brokerClient, - ApplicationEventPublisher publisher) { - this.brokerClient = brokerClient; - this.publisher = publisher; - } - - @Override - public void onApplicationEvent(ApplicationReadyEvent event) { - // TODO: is there a better event the just RSocketRequester? - // TODO: save Disposable? - this.brokerClient.connect().subscribe(publishEvent()); - } - - private Consumer publishEvent() { - return requester -> publisher.publishEvent(new RSocketRequesterEvent<>( - BrokerClientConnectionListener.this, requester)); - } - - @Override - public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE; // TODO: configurable - } - - private static final class RSocketRequesterEvent - extends PayloadApplicationEvent { - - private RSocketRequesterEvent(Object source, T payload) { - super(source, payload); - } - - @Override - public ResolvableType getResolvableType() { - return ResolvableType.forClassWithGenerics(getClass(), - ResolvableType.forClass(RSocketRequester.class)); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientProperties.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientProperties.java deleted file mode 100644 index ee64ada8..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientProperties.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.client; - -import java.math.BigInteger; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Objects; -import java.util.StringJoiner; - -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.NestedConfigurationProperty; -import org.springframework.cloud.gateway.rsocket.common.autoconfigure.Broker; -import org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey; -import org.springframework.core.style.ToStringCreator; -import org.springframework.util.StringUtils; -import org.springframework.validation.annotation.Validated; - -@ConfigurationProperties("spring.cloud.gateway.rsocket.client") -@Validated -public class ClientProperties { - - @NotNull - private BigInteger routeId; - - @NotEmpty - private String serviceName; - - private Map tags = new LinkedHashMap<>(); - - @Valid - @NestedConfigurationProperty - private Broker broker = new Broker(); - - private Map> forwarding = new LinkedHashMap<>(); - - public BigInteger getRouteId() { - return this.routeId; - } - - public void setRouteId(BigInteger routeId) { - this.routeId = routeId; - } - - public String getServiceName() { - return this.serviceName; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public Map getTags() { - return tags; - } - - public Broker getBroker() { - return this.broker; - } - - public void setBroker(Broker broker) { - this.broker = broker; - } - - public Map> getForwarding() { - return forwarding; - } - - @Override - public String toString() { - // @formatter:off - return new ToStringCreator(this) - .append("routeId", routeId) - .append("serviceName", serviceName) - .append("tags", tags) - .append("broker", broker) - .append("forwarding", forwarding) - .toString(); - // @formatter:on - } - - public static class TagKey { - - private WellKnownKey wellKnownKey; - - private String customKey; - - public TagKey() { - System.out.println("here"); - } - - public TagKey(String text) { - if (!StringUtils.isEmpty(text)) { - try { - wellKnownKey = WellKnownKey.valueOf(text.toUpperCase()); - } - catch (IllegalArgumentException e) { - // NOT a valid well know key - customKey = text; - } - } - } - - public static TagKey of(WellKnownKey key) { - TagKey tagKey = new TagKey(); - tagKey.setWellKnownKey(key); - return tagKey; - } - - public static TagKey of(String key) { - return new TagKey(key); - } - - public WellKnownKey getWellKnownKey() { - return wellKnownKey; - } - - public void setWellKnownKey(WellKnownKey wellKnownKey) { - this.wellKnownKey = wellKnownKey; - } - - public String getCustomKey() { - return customKey; - } - - public void setCustomKey(String customKey) { - this.customKey = customKey; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - TagKey tag = (TagKey) o; - return wellKnownKey == tag.wellKnownKey - && Objects.equals(customKey, tag.customKey); - } - - @Override - public int hashCode() { - return Objects.hash(wellKnownKey, customKey); - } - - @Override - public String toString() { - StringJoiner joiner = new StringJoiner(", ", "[", "]"); - if (wellKnownKey != null) { - joiner.add(wellKnownKey.name()); - } - if (customKey != null) { - joiner.add("'" + customKey + "'"); - } - return joiner.toString(); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequester.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequester.java deleted file mode 100644 index f32136f8..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequester.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.client; - -import java.math.BigInteger; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import io.rsocket.RSocket; - -import org.springframework.cloud.gateway.rsocket.client.ClientProperties.TagKey; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.lang.Nullable; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.util.Assert; -import org.springframework.util.MimeType; -import org.springframework.util.ObjectUtils; -import org.springframework.util.RouteMatcher; - -final class ClientRSocketRequester implements RSocketRequester { - - /** For route variable replacement. */ - private static final Pattern NAMES_PATTERN = Pattern.compile("\\{([^/]+?)\\}"); - - private final RSocketRequester delegate; - - private final ClientProperties properties; - - private final RouteMatcher routeMatcher; - - ClientRSocketRequester(RSocketRequester delegate, ClientProperties properties, - RouteMatcher routeMatcher) { - this.delegate = delegate; - this.properties = properties; - this.routeMatcher = routeMatcher; - } - - @Override - public RSocket rsocket() { - return delegate.rsocket(); - } - - @Override - public MimeType dataMimeType() { - return delegate.dataMimeType(); - } - - @Override - public MimeType metadataMimeType() { - return delegate.metadataMimeType(); - } - - @Override - public RequestSpec route(String route, Object... routeVars) { - RequestSpec requestSpec = delegate.route(route, routeVars); - // needs to be expanded with routeVars - RouteMatcher.Route parsed = routeMatcher.parseRoute(expand(route, routeVars)); - - properties.getForwarding().entrySet().stream() - .filter(entry -> routeMatcher.match(entry.getKey(), parsed)).findFirst() - .ifPresent(entry -> { - Forwarding.Builder forwarding = forwarding(routeMatcher, parsed, - properties.getRouteId(), entry.getKey(), entry.getValue()); - - requestSpec.metadata(forwarding.build(), - Forwarding.FORWARDING_MIME_TYPE); - }); - - return requestSpec; - } - - /* for testing */ static Forwarding.Builder forwarding(RouteMatcher routeMatcher, - RouteMatcher.Route route, BigInteger originRouteId, String routeKey, - Map tags) { - Map extracted = routeMatcher.matchAndExtract(routeKey, route); - Forwarding.Builder forwarding = Forwarding.of(originRouteId); - - tags.forEach((tagKey, value) -> { - if (tagKey.getWellKnownKey() != null) { - forwarding.with(tagKey.getWellKnownKey(), expand(value, extracted)); - } - else if (tagKey.getCustomKey() != null) { - forwarding.with(tagKey.getCustomKey(), expand(value, extracted)); - } - }); - return forwarding; - } - - @Override - public RequestSpec metadata(Object metadata, MimeType mimeType) { - return delegate.metadata(metadata, mimeType); - } - - /* for testing */ static String expand(String route, Object... routeVars) { - if (ObjectUtils.isEmpty(routeVars)) { - return route; - } - StringBuffer sb = new StringBuffer(); - int index = 0; - Matcher matcher = NAMES_PATTERN.matcher(route); - while (matcher.find()) { - Assert.isTrue(index < routeVars.length, - () -> "No value for variable '" + matcher.group(1) + "'"); - String value = routeVars[index].toString(); - value = value.contains(".") ? value.replaceAll("\\.", "%2E") : value; - matcher.appendReplacement(sb, value); - index++; - } - return sb.toString(); - } - - /* for testing */ static String expand(String template, Map vars) { - if (template == null) { - return null; - } - if (template.indexOf('{') == -1) { - return template; - } - if (template.indexOf(':') != -1) { - template = sanitizeSource(template); - } - - if (ObjectUtils.isEmpty(vars)) { - return template; - } - - StringBuffer sb = new StringBuffer(); - Matcher matcher = NAMES_PATTERN.matcher(template); - while (matcher.find()) { - String match = matcher.group(1); - String varName = getVariableName(match); - Object varValue = vars.get(varName); - String formatted = getVariableValueAsString(varValue); - matcher.appendReplacement(sb, formatted); - } - matcher.appendTail(sb); - return sb.toString(); - } - - /** - * Remove nested "{}" such as in URI vars with regular expressions. - */ - private static String sanitizeSource(String source) { - int level = 0; - StringBuilder sb = new StringBuilder(); - for (char c : source.toCharArray()) { - if (c == '{') { - level++; - } - if (c == '}') { - level--; - } - if (level > 1 || (level == 1 && c == '}')) { - continue; - } - sb.append(c); - } - return sb.toString(); - } - - private static String getVariableName(String match) { - int colonIdx = match.indexOf(':'); - return (colonIdx != -1 ? match.substring(0, colonIdx) : match); - } - - private static String getVariableValueAsString(@Nullable Object variableValue) { - return (variableValue != null ? variableValue.toString() : ""); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequesterBuilder.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequesterBuilder.java deleted file mode 100644 index 56f757f3..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequesterBuilder.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.client; - -import java.net.URI; -import java.util.function.Consumer; - -import io.rsocket.transport.ClientTransport; -import io.rsocket.transport.netty.client.TcpClientTransport; -import io.rsocket.transport.netty.client.WebsocketClientTransport; -import reactor.core.publisher.Mono; - -import org.springframework.messaging.rsocket.ClientRSocketFactoryConfigurer; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.messaging.rsocket.RSocketStrategies; -import org.springframework.util.MimeType; -import org.springframework.util.RouteMatcher; - -final class ClientRSocketRequesterBuilder implements RSocketRequester.Builder { - - private final RSocketRequester.Builder delegate; - - private final ClientProperties properties; - - private final RouteMatcher routeMatcher; - - ClientRSocketRequesterBuilder(RSocketRequester.Builder delegate, - ClientProperties properties, RouteMatcher routeMatcher) { - this.delegate = delegate; - this.properties = properties; - this.routeMatcher = routeMatcher; - } - - @Override - public RSocketRequester.Builder dataMimeType(MimeType mimeType) { - return delegate.dataMimeType(mimeType); - } - - @Override - public RSocketRequester.Builder metadataMimeType(MimeType mimeType) { - return delegate.metadataMimeType(mimeType); - } - - @Override - public RSocketRequester.Builder setupData(Object data) { - return delegate.setupData(data); - } - - @Override - public RSocketRequester.Builder setupRoute(String route, Object... routeVars) { - return delegate.setupRoute(route, routeVars); - } - - @Override - public RSocketRequester.Builder setupMetadata(Object value, MimeType mimeType) { - return delegate.setupMetadata(value, mimeType); - } - - @Override - public RSocketRequester.Builder rsocketStrategies(RSocketStrategies strategies) { - return delegate.rsocketStrategies(strategies); - } - - @Override - public RSocketRequester.Builder rsocketStrategies( - Consumer configurer) { - return delegate.rsocketStrategies(configurer); - } - - @Override - public RSocketRequester.Builder rsocketFactory( - ClientRSocketFactoryConfigurer configurer) { - return delegate.rsocketFactory(configurer); - } - - @Override - public RSocketRequester.Builder apply(Consumer configurer) { - return delegate.apply(configurer); - } - - @Override - public Mono connectTcp(String host, int port) { - return connect(TcpClientTransport.create(host, port)); - } - - @Override - public Mono connectWebSocket(URI uri) { - return connect(WebsocketClientTransport.create(uri)); - } - - @Override - public Mono connect(ClientTransport transport) { - return delegate.connect(transport) - .map(requester -> new ClientRSocketRequester(requester, properties, - routeMatcher)); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/GatewayRSocketClientAutoConfiguration.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/GatewayRSocketClientAutoConfiguration.java deleted file mode 100644 index adb6b05e..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/java/org/springframework/cloud/gateway/rsocket/client/GatewayRSocketClientAutoConfiguration.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.client; - -import java.math.BigInteger; -import java.util.function.Supplier; - -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tag; -import io.rsocket.RSocket; -import io.rsocket.micrometer.MicrometerRSocketInterceptor; -import io.rsocket.plugins.RSocketInterceptor; - -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration; -import org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Scope; -import org.springframework.messaging.rsocket.ClientRSocketFactoryConfigurer; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.messaging.rsocket.RSocketStrategies; -import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; - -import static org.springframework.cloud.gateway.rsocket.common.autoconfigure.GatewayRSocketCommonAutoConfiguration.ID_GENERATOR_BEAN_NAME; - -/** - * @author Spencer Gibb - */ -@Configuration -// TODO: add this property to config metadata -@ConditionalOnProperty(name = "spring.cloud.gateway.rsocket.enabled", - matchIfMissing = true) -@EnableConfigurationProperties -@ConditionalOnClass({ RSocket.class, RSocketRequester.class }) -@AutoConfigureAfter(RSocketStrategiesAutoConfiguration.class) -@AutoConfigureBefore(RSocketRequesterAutoConfiguration.class) -public class GatewayRSocketClientAutoConfiguration { - - private final RSocketMessageHandler messageHandler; - - public GatewayRSocketClientAutoConfiguration(RSocketMessageHandler handler) { - messageHandler = handler; - } - - @Bean - @Scope("prototype") // TODO: I don't think prototype works here - @ConditionalOnMissingBean - public RSocketRequester.Builder gatewayRSocketRequesterBuilder( - RSocketStrategies strategies, ClientProperties properties, - MeterRegistry meterRegistry) { - RouteSetup.Builder routeSetup = RouteSetup.of(properties.getRouteId(), - properties.getServiceName()); - properties.getTags().forEach((key, value) -> { - if (key.getWellKnownKey() != null) { - routeSetup.with(key.getWellKnownKey(), value); - } - else if (key.getCustomKey() != null) { - routeSetup.with(key.getCustomKey(), value); - } - }); - - MicrometerRSocketInterceptor interceptor = new MicrometerRSocketInterceptor( - meterRegistry, Tag.of("servicename", properties.getServiceName())); - - RSocketRequester.Builder builder = RSocketRequester.builder() - .setupMetadata(routeSetup.build(), RouteSetup.ROUTE_SETUP_MIME_TYPE) - .rsocketStrategies(strategies).rsocketFactory(configurer(interceptor)); - - return new ClientRSocketRequesterBuilder(builder, properties, - strategies.routeMatcher()); - } - - private ClientRSocketFactoryConfigurer configurer(RSocketInterceptor interceptor) { - return rsocketFactory -> rsocketFactory.addRequesterPlugin(interceptor) - .acceptor(messageHandler.responder()); - } - - @Bean - public BrokerClient brokerClient(RSocketRequester.Builder builder, - ClientProperties properties) { - return new BrokerClient(properties, builder); - } - - @Bean - @ConditionalOnProperty(name = "spring.cloud.gateway.rsocket.client.auto-connect", - matchIfMissing = true) - public BrokerClientConnectionListener brokerClientConnectionListener( - BrokerClient client, ApplicationEventPublisher publisher) { - return new BrokerClientConnectionListener(client, publisher); - } - - @Bean - public ClientProperties clientProperties( - @Qualifier(ID_GENERATOR_BEAN_NAME) Supplier idGenerator) { - ClientProperties clientProperties = new ClientProperties(); - clientProperties.setRouteId(idGenerator.get()); - return clientProperties; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/resources/META-INF/spring.factories b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 63451731..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -# Auto Configure -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.gateway.rsocket.client.GatewayRSocketClientAutoConfiguration diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/java/org/springframework/cloud/gateway/rsocket/client/ClientPropertiesTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/java/org/springframework/cloud/gateway/rsocket/client/ClientPropertiesTests.java deleted file mode 100644 index 7183123f..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/java/org/springframework/cloud/gateway/rsocket/client/ClientPropertiesTests.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.client; - -import java.util.Map; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.gateway.rsocket.client.ClientProperties.TagKey; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.entry; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT, - properties = "spring.cloud.gateway.rsocket.client.auto-connect=false") -public class ClientPropertiesTests { - - @Autowired - ClientProperties properties; - - @Test - public void clientProperties() { - assertThat(properties).isNotNull(); - assertThat(properties.getRouteId()).isEqualTo(11L); - assertThat(properties.getServiceName()).isEqualTo("test_requester"); - assertThat(properties.getTags()).containsEntry(TagKey.of("INSTANCE_NAME"), - "test_requester1"); - assertThat(properties.getForwarding()).containsKey("test_responder-rc"); - Map map = properties.getForwarding().get("test_responder-rc"); - assertThat(map).contains(entry(TagKey.of("SERVICE_NAME"), "test_responder"), - entry(TagKey.of("custom-tag"), "custom-value")); - assertThat(properties.getBroker()).isNotNull().extracting("host", "port") - .containsExactly("localhost", 7002); - } - - @SpringBootConfiguration - @EnableAutoConfiguration - static class Config { - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequesterTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequesterTests.java deleted file mode 100644 index 0461037b..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/java/org/springframework/cloud/gateway/rsocket/client/ClientRSocketRequesterTests.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.client; - -import java.math.BigInteger; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.junit.jupiter.api.Test; - -import org.springframework.cloud.gateway.rsocket.client.ClientProperties.TagKey; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata.Key; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.RouteMatcher; -import org.springframework.util.SimpleRouteMatcher; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.rsocket.client.ClientRSocketRequester.expand; -import static org.springframework.cloud.gateway.rsocket.client.ClientRSocketRequester.forwarding; -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.ROUTE_ID; -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.SERVICE_NAME; - -public class ClientRSocketRequesterTests { - - @Test - public void forwardingWorks() { - RouteMatcher routeMatcher = new SimpleRouteMatcher(new AntPathMatcher(".")); - RouteMatcher.Route route = routeMatcher.parseRoute("myroute.foo1.bar1"); - LinkedHashMap tags = new LinkedHashMap<>(); - tags.put(TagKey.of(SERVICE_NAME), "{foo}"); - tags.put(TagKey.of(ROUTE_ID), "22"); - tags.put(TagKey.of("mycustomkey"), "{foo}-{bar}"); - Forwarding fwd = (Forwarding) forwarding(routeMatcher, route, - new BigInteger("11"), "myroute.{foo}.{bar}", tags).build(); - - assertThat(fwd).isNotNull(); - assertThat(fwd.getEnrichedTagsMetadata().getTags()).isNotEmpty() - .containsEntry(new Key(SERVICE_NAME), "foo1") - .containsEntry(new Key(ROUTE_ID), "22") - .containsEntry(new Key("mycustomkey"), "foo1-bar1"); - } - - @Test - public void expandArrayVars() { - String result = expand("myroute.{foo}.{bar}", "foo1", "bar1"); - assertThat(result).isEqualTo("myroute.foo1.bar1"); - } - - @Test - public void expandMapVars() { - HashMap map = new HashMap<>(); - map.put("value", "a+b"); - map.put("city", "Z\u00fcrich"); - String result = expand("/hotel list/{city} specials/{value}", map); - - assertThat(result).isEqualTo("/hotel list/Z\u00fcrich specials/a+b"); - } - - @Test - public void expandPartially() { - HashMap map = new HashMap<>(); - map.put("city", "Z\u00fcrich"); - String result = expand("/hotel list/{city} specials/{value}", map); - - assertThat(result).isEqualTo("/hotel list/Zürich specials/"); - } - - @Test - public void expandSimple() { - HashMap map = new HashMap<>(); - map.put("foo", "1 2"); - map.put("bar", "3 4"); - String result = expand("/{foo} {bar}", map); - assertThat(result).isEqualTo("/1 2 3 4"); - } - - @Test // SPR-13311 - public void expandWithRegexVar() { - String template = "/myurl/{name:[a-z]{1,5}}/show"; - Map map = Collections.singletonMap("name", "test"); - String result = expand(template, map); - assertThat(result).isEqualTo("/myurl/test/show"); - } - - @Test // SPR-17630 - public void expandWithMismatchedCurlyBraces() { - String result = expand("/myurl/{{{{", Collections.emptyMap()); - assertThat(result).isEqualTo("/myurl/{{{{"); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/resources/application.yml b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/resources/application.yml deleted file mode 100644 index b2ea6bdd..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-client/src/test/resources/application.yml +++ /dev/null @@ -1,12 +0,0 @@ -spring.cloud.gateway.rsocket.client: - route-id: 11 - service-name: test_requester - tags: - INSTANCE_NAME: test_requester1 - forwarding: - test_responder-rc: - service_name: test_responder - custom-tag: custom-value - broker: - host: localhost - port: 7002 diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/pom.xml b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/pom.xml deleted file mode 100644 index 8a9d1b3f..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/pom.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - - - 4.0.0 - - org.springframework.cloud - spring-cloud-gateway-rsocket - 2.2.0.BUILD-SNAPSHOT - .. - - org.springframework.cloud - spring-cloud-gateway-rsocket-common - Spring Cloud Gateway RSocket Common - Spring Cloud Gateway RSocket Common - - - - org.springframework.boot - spring-boot-starter-rsocket - - - org.springframework.boot - spring-boot-starter-validation - - - org.springframework.boot - spring-boot-configuration-processor - true - - - io.rsocket - rsocket-core - - - io.rsocket - rsocket-micrometer - - - io.rsocket - rsocket-transport-netty - - - io.micrometer - micrometer-core - - - org.roaringbitmap - RoaringBitmap - - - org.springframework.boot - spring-boot-starter-actuator - test - - - org.projectlombok - lombok - test - - - org.springframework.boot - spring-boot-starter-test - test - - - io.projectreactor - reactor-test - test - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - -parameters - - - - - - default-compile - none - - - - default-testCompile - none - - - java-compile - compile - - compile - - - - java-test-compile - test-compile - - testCompile - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.1.0 - - - - test-jar - - - - - - - - - java8plus - - [1.8,2.0) - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - -parameters - - - - - - - - - diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/Broker.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/Broker.java deleted file mode 100644 index 41a532a8..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/Broker.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.autoconfigure; - -import java.net.URI; - -import javax.validation.constraints.NotNull; - -import org.springframework.core.style.ToStringCreator; - -public class Broker { - - public enum ConnectionType { - - /** TCP RSocket connection. */ - TCP, - /** WEBSOCKET RSocket connection. */ - WEBSOCKET - - } - - // FIXME: validate based on connectionType - private String host; - - private int port; - - @NotNull - private ConnectionType connectionType = ConnectionType.TCP; - - private URI wsUri; - - public String getHost() { - return this.host; - } - - public void setHost(String host) { - this.host = host; - } - - public int getPort() { - return this.port; - } - - public void setPort(int port) { - this.port = port; - } - - public ConnectionType getConnectionType() { - return this.connectionType; - } - - public void setConnectionType(ConnectionType connectionType) { - this.connectionType = connectionType; - } - - public URI getWsUri() { - return this.wsUri; - } - - public void setWsUri(URI wsUri) { - this.wsUri = wsUri; - } - - @Override - public String toString() { - // @formatter:off - return new ToStringCreator(this) - .append("host", host) - .append("port", port) - .append("wsUri", wsUri) - .append("connectionType", connectionType) - .toString(); - // @formatter:on - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/GatewayRSocketCommonAutoConfiguration.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/GatewayRSocketCommonAutoConfiguration.java deleted file mode 100644 index c5a3025d..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/GatewayRSocketCommonAutoConfiguration.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.autoconfigure; - -import java.math.BigInteger; -import java.security.SecureRandom; -import java.util.function.Supplier; - -import io.rsocket.RSocket; - -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.rsocket.messaging.RSocketStrategiesCustomizer; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author Spencer Gibb - */ -@Configuration -@ConditionalOnProperty(name = "spring.cloud.gateway.rsocket.enabled", - matchIfMissing = true) -@EnableConfigurationProperties -@ConditionalOnClass(RSocket.class) -@AutoConfigureBefore(RSocketStrategiesAutoConfiguration.class) -public class GatewayRSocketCommonAutoConfiguration { - - /** - * Name of id generator bean. - */ - public static final String ID_GENERATOR_BEAN_NAME = "gatewayRSocketIdGenerator"; - - private final SecureRandom secureRandom = new SecureRandom(); - - @Bean - public RSocketStrategiesCustomizer gatewayRSocketStrategiesCustomizer() { - return strategies -> { - strategies.decoder(new Forwarding.Decoder(), new RouteSetup.Decoder()) - .encoder(new Forwarding.Encoder(), new RouteSetup.Encoder()); - }; - } - - @Bean(name = ID_GENERATOR_BEAN_NAME) - @ConditionalOnMissingBean(name = ID_GENERATOR_BEAN_NAME) - public Supplier gatewayRSocketIdGenerator() { - return () -> { - byte[] bytes = new byte[16]; - secureRandom.nextBytes(bytes); - return new BigInteger(bytes); - }; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/GatewayRSocketCommonMetadataAutoConfiguration.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/GatewayRSocketCommonMetadataAutoConfiguration.java deleted file mode 100644 index 0335265b..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/autoconfigure/GatewayRSocketCommonMetadataAutoConfiguration.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.autoconfigure; - -import io.rsocket.RSocket; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding; -import org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.rsocket.DefaultMetadataExtractor; -import org.springframework.messaging.rsocket.MetadataExtractor; -import org.springframework.messaging.rsocket.RSocketStrategies; - -import static org.springframework.cloud.gateway.rsocket.common.metadata.Forwarding.FORWARDING_MIME_TYPE; -import static org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetup.ROUTE_SETUP_MIME_TYPE; - -/** - * @author Spencer Gibb - */ -@Configuration -@ConditionalOnProperty(name = "spring.cloud.gateway.rsocket.enabled", - matchIfMissing = true) -@EnableConfigurationProperties -@ConditionalOnClass(RSocket.class) -@AutoConfigureAfter({ GatewayRSocketCommonAutoConfiguration.class }) -public class GatewayRSocketCommonMetadataAutoConfiguration implements InitializingBean { - - private final ApplicationContext context; - - public GatewayRSocketCommonMetadataAutoConfiguration(ApplicationContext context) { - this.context = context; - } - - @Override - public void afterPropertiesSet() { - RSocketStrategies rSocketStrategies = this.context - .getBean(RSocketStrategies.class); - MetadataExtractor metadataExtractor = rSocketStrategies.metadataExtractor(); - // TODO: see if possible to make easier in framework. - if (metadataExtractor instanceof DefaultMetadataExtractor) { - DefaultMetadataExtractor extractor = (DefaultMetadataExtractor) metadataExtractor; - extractor.metadataToExtract(FORWARDING_MIME_TYPE, Forwarding.class, - Forwarding.METADATA_KEY); - extractor.metadataToExtract(ROUTE_SETUP_MIME_TYPE, RouteSetup.class, - RouteSetup.METADATA_KEY); - } - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/Forwarding.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/Forwarding.java deleted file mode 100644 index eb6fe107..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/Forwarding.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import java.math.BigInteger; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.core.ResolvableType; -import org.springframework.core.codec.AbstractDecoder; -import org.springframework.core.codec.AbstractEncoder; -import org.springframework.core.codec.DecodingException; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.core.io.buffer.NettyDataBufferFactory; -import org.springframework.core.style.ToStringCreator; -import org.springframework.util.Assert; -import org.springframework.util.MimeType; - -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.ROUTE_ID; -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.SERVICE_NAME; - -// TODO: currently an ENVELOPE frame in RSocket extension, also discarding metadata -public final class Forwarding extends TagsMetadata { - - /** - * Forwarding metadata key. - */ - public static final String METADATA_KEY = "forwarding"; - - /** - * Forwarding subtype. - */ - public static final String FORWARDING = "x.rsocket.forwarding.v0"; - - /** - * Forwarding mimetype. - */ - public static final MimeType FORWARDING_MIME_TYPE = new MimeType("message", - FORWARDING); - - private final BigInteger originRouteId; - - private Forwarding(BigInteger originRouteId, Map tags) { - super(tags); - this.originRouteId = originRouteId; - } - - public static Builder of(long originRouteId) { - return of(BigInteger.valueOf(originRouteId)); - } - - public static Builder of(BigInteger originRouteId) { - return new Builder(originRouteId); - } - - public BigInteger getOriginRouteId() { - return this.originRouteId; - } - - public ByteBuf encode() { - return encode(this); - } - - @Override - public String toString() { - // @formatter:off - return new ToStringCreator(this) - .append("originRouteId", originRouteId) - .append("tags", getTags()) - .toString(); - // @formatter:on - } - - static ByteBuf encode(Forwarding forwarding) { - return encode(ByteBufAllocator.DEFAULT, forwarding); - } - - static ByteBuf encode(ByteBufAllocator allocator, Forwarding forwarding) { - Assert.notNull(forwarding, "forwarding may not be null"); - Assert.notNull(allocator, "allocator may not be null"); - ByteBuf byteBuf = allocator.buffer(); - - encodeBigInteger(byteBuf, forwarding.originRouteId); - - encode(byteBuf, forwarding.getTags()); - - return byteBuf; - } - - static Forwarding decodeForwarding(ByteBuf byteBuf) { - AtomicInteger offset = new AtomicInteger(0); - - BigInteger originRouteId = decodeBigInteger(byteBuf, offset); - - TagsMetadata tagsMetadata = decode(offset, byteBuf); - - Forwarding forwarding = new Forwarding(originRouteId, tagsMetadata.getTags()); - - return forwarding; - } - - public static class Encoder extends AbstractEncoder { - - public Encoder() { - super(Forwarding.FORWARDING_MIME_TYPE); - } - - @Override - public Flux encode(Publisher inputStream, - DataBufferFactory bufferFactory, ResolvableType elementType, - MimeType mimeType, Map hints) { - throw new UnsupportedOperationException("stream encoding not supported."); - } - - @Override - public DataBuffer encodeValue(Forwarding value, DataBufferFactory bufferFactory, - ResolvableType valueType, MimeType mimeType, Map hints) { - NettyDataBufferFactory factory = (NettyDataBufferFactory) bufferFactory; - ByteBuf encoded = Forwarding.encode(factory.getByteBufAllocator(), value); - return factory.wrap(encoded); - } - - } - - public static class Decoder extends AbstractDecoder { - - public Decoder() { - super(Forwarding.FORWARDING_MIME_TYPE); - } - - @Override - public Flux decode(Publisher inputStream, - ResolvableType elementType, MimeType mimeType, - Map hints) { - throw new UnsupportedOperationException("stream decoding not supported."); - } - - @Override - public Forwarding decode(DataBuffer buffer, ResolvableType targetType, - MimeType mimeType, Map hints) throws DecodingException { - ByteBuf byteBuf = TagsMetadata.asByteBuf(buffer); - return Forwarding.decodeForwarding(byteBuf); - } - - } - - public final static class Builder { - - private final BigInteger originRouteId; - - private final TagsMetadata.Builder tagsBuilder = TagsMetadata.builder(); - - private Builder(BigInteger originRouteId) { - // Assert.notNull(id, "id may not be null"); - this.originRouteId = originRouteId; - } - - public Builder with(String key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(WellKnownKey key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(Key key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(TagsMetadata tagsMetadata) { - tagsBuilder.with(tagsMetadata); - return this; - } - - public Builder routeId(String routeId) { - tagsBuilder.with(ROUTE_ID, routeId); - return this; - } - - public Builder serviceName(String serviceName) { - tagsBuilder.with(SERVICE_NAME, serviceName); - return this; - } - - public Builder disableProxy() { - // TODO: move to well known implementation key - tagsBuilder.with("proxy", Boolean.FALSE.toString()); - return this; - } - - public Forwarding build() { - return new Forwarding(originRouteId, tagsBuilder.build().getTags()); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/Metadata.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/Metadata.java deleted file mode 100644 index db31f271..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/Metadata.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import io.rsocket.metadata.WellKnownMimeType; - -import org.springframework.util.MimeType; - -public abstract class Metadata { - - /** - * Composite Metadata MimeType. - */ - public static final MimeType COMPOSITE_MIME_TYPE = MimeType - .valueOf(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.toString()); - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetup.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetup.java deleted file mode 100644 index 3563d364..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetup.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import java.math.BigInteger; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; - -import org.springframework.core.ResolvableType; -import org.springframework.core.codec.AbstractDecoder; -import org.springframework.core.codec.AbstractEncoder; -import org.springframework.core.codec.DecodingException; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.core.io.buffer.NettyDataBufferFactory; -import org.springframework.core.style.ToStringCreator; -import org.springframework.util.Assert; -import org.springframework.util.MimeType; - -public final class RouteSetup extends TagsMetadata { - - /** - * Forwarding metadata key. - */ - public static final String METADATA_KEY = "routesetup"; - - /** - * Route Setup subtype. - */ - public static final String ROUTE_SETUP = "x.rsocket.routesetup.v0"; - - /** - * Route Setup mime type. - */ - public static final MimeType ROUTE_SETUP_MIME_TYPE = new MimeType("message", - ROUTE_SETUP); - - private final BigInteger id; - - private final String serviceName; - - private RouteSetup(BigInteger id, String serviceName, Map tags) { - super(tags); - this.id = id; - this.serviceName = serviceName; - } - - public BigInteger getId() { - return this.id; - } - - public String getServiceName() { - return this.serviceName; - } - - public ByteBuf encode() { - return encode(this); - } - - @Override - public TagsMetadata getEnrichedTagsMetadata() { - // @formatter:off - TagsMetadata tagsMetadata = TagsMetadata.builder(this) - .with(WellKnownKey.SERVICE_NAME, getServiceName()) - .with(WellKnownKey.ROUTE_ID, id == null ? null : getId().toString()) - .build(); - // @formatter:on - - return tagsMetadata; - } - - @Override - public String toString() { - // @formatter:off - return new ToStringCreator(this) - .append("id", id) - .append("serviceName", serviceName) - .append("tags", getTags()) - .toString(); - // @formatter:on - } - - public static Builder of(BigInteger id, String serviceName) { - return new Builder(id, serviceName); - } - - public static Builder of(Long id, String serviceName) { - return of(BigInteger.valueOf(id), serviceName); - } - - static ByteBuf encode(RouteSetup routeSetup) { - return encode(ByteBufAllocator.DEFAULT, routeSetup); - } - - static ByteBuf encode(ByteBufAllocator allocator, RouteSetup routeSetup) { - Assert.notNull(routeSetup, "routeSetup may not be null"); - Assert.notNull(allocator, "allocator may not be null"); - ByteBuf byteBuf = allocator.buffer(); - - encodeBigInteger(byteBuf, routeSetup.id); - - encodeString(byteBuf, routeSetup.getServiceName()); - - encode(byteBuf, routeSetup.getTags()); - - return byteBuf; - } - - static RouteSetup decodeRouteSetup(ByteBuf byteBuf) { - AtomicInteger offset = new AtomicInteger(0); - - BigInteger id = decodeBigInteger(byteBuf, offset); - - String serviceName = decodeString(byteBuf, offset); - - TagsMetadata tagsMetadata = decode(offset, byteBuf); - - RouteSetup routeSetup = new RouteSetup(id, serviceName, tagsMetadata.getTags()); - - return routeSetup; - } - - public static class Encoder extends AbstractEncoder { - - public Encoder() { - super(ROUTE_SETUP_MIME_TYPE); - } - - @Override - public Flux encode(Publisher inputStream, - DataBufferFactory bufferFactory, ResolvableType elementType, - MimeType mimeType, Map hints) { - throw new UnsupportedOperationException("stream encoding not supported."); - } - - @Override - public DataBuffer encodeValue(RouteSetup value, DataBufferFactory bufferFactory, - ResolvableType valueType, MimeType mimeType, Map hints) { - NettyDataBufferFactory factory = (NettyDataBufferFactory) bufferFactory; - ByteBuf encoded = RouteSetup.encode(factory.getByteBufAllocator(), value); - return factory.wrap(encoded); - } - - } - - public static class Decoder extends AbstractDecoder { - - public Decoder() { - super(ROUTE_SETUP_MIME_TYPE); - } - - @Override - public Flux decode(Publisher inputStream, - ResolvableType elementType, MimeType mimeType, - Map hints) { - throw new UnsupportedOperationException("stream decoding not supported."); - } - - @Override - public RouteSetup decode(DataBuffer buffer, ResolvableType targetType, - MimeType mimeType, Map hints) throws DecodingException { - ByteBuf byteBuf = TagsMetadata.asByteBuf(buffer); - return RouteSetup.decodeRouteSetup(byteBuf); - } - - } - - public static final class Builder { - - private final BigInteger id; - - private final String serviceName; - - private final TagsMetadata.Builder tagsBuilder = TagsMetadata.builder(); - - private Builder(BigInteger id, String serviceName) { - // Assert.notNull(id, "id may not be null"); - // Assert.hasText(serviceName, "serviceName may not be empty"); - this.id = id; - this.serviceName = serviceName; - } - - public Builder with(String key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(WellKnownKey key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(Key key, String value) { - tagsBuilder.with(key, value); - return this; - } - - public Builder with(TagsMetadata tagsMetadata) { - tagsBuilder.with(tagsMetadata); - return this; - } - - public RouteSetup build() { - return new RouteSetup(id, serviceName, tagsBuilder.build().getTags()); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/TagsMetadata.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/TagsMetadata.java deleted file mode 100644 index 116bdf44..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/TagsMetadata.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Objects; -import java.util.StringJoiner; -import java.util.concurrent.atomic.AtomicInteger; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.ByteBufUtil; -import io.netty.buffer.Unpooled; -import io.rsocket.util.NumberUtils; - -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.NettyDataBuffer; -import org.springframework.util.Assert; - -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.ROUTE_ID; -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.SERVICE_NAME; - -public class TagsMetadata { - - private static final Key ROUTE_ID_KEY = new Key(ROUTE_ID); - - private static final int WELL_KNOWN_TAG = 0x80; - - private static final int HAS_MORE_TAGS = 0x80; - - private static final int MAX_TAG_LENGTH = 0x7F; - - private final Map tags; - - protected TagsMetadata(Map tags) { - this.tags = tags; - } - - public static ByteBuf asByteBuf(DataBuffer buffer) { - return buffer instanceof NettyDataBuffer - ? ((NettyDataBuffer) buffer).getNativeBuffer() - : Unpooled.wrappedBuffer(buffer.asByteBuffer()); - } - - public Map getTags() { - return this.tags; - } - - public String getRouteId() { - return this.tags.get(ROUTE_ID_KEY); - } - - public String get(WellKnownKey key) { - return this.tags.get(new Key(key)); - } - - public String put(Key key, String value) { - return this.tags.put(key, value); - } - - /** - * Allows subclasses to enrich tags before use. - * @return by default, this. - */ - public TagsMetadata getEnrichedTagsMetadata() { - return this; - } - - @Override - public String toString() { - return "TagsMetadata" + tags; - } - - public static Builder builder() { - return new Builder(); - } - - public static Builder builder(TagsMetadata existing) { - Builder builder = new Builder(); - return builder.with(existing); - } - - protected static ByteBuf encode(TagsMetadata metadata) { - return encode(ByteBufAllocator.DEFAULT, metadata.tags); - } - - protected static ByteBuf encode(ByteBufAllocator allocator, Map tags) { - Assert.notNull(tags, "tags may not be null"); - Assert.notNull(allocator, "allocator may not be null"); - ByteBuf byteBuf = allocator.buffer(); - return encode(byteBuf, tags); - } - - protected static ByteBuf encode(ByteBuf byteBuf, Map tags) { - Assert.notNull(byteBuf, "byteBuf may not be null"); - - Iterator> it = tags.entrySet().iterator(); - - while (it.hasNext()) { - Map.Entry entry = it.next(); - Key key = entry.getKey(); - if (key.wellKnownKey != null) { - byte id = key.wellKnownKey.getIdentifier(); - int keyLength = WELL_KNOWN_TAG | id; - byteBuf.writeByte(keyLength); - } - else { - String keyString = key.key; - if (keyString == null) { - continue; - } - int keyLength = ByteBufUtil.utf8Bytes(keyString); - if (keyLength == 0 || keyLength > MAX_TAG_LENGTH) { - continue; - } - byteBuf.writeByte(keyLength); - ByteBufUtil.reserveAndWriteUtf8(byteBuf, keyString, keyLength); - } - - boolean hasMoreTags = it.hasNext(); - - String value = entry.getValue(); - int valueLength = ByteBufUtil.utf8Bytes(value); - if (valueLength == 0 || valueLength > MAX_TAG_LENGTH) { - continue; - } - int valueByte; - if (hasMoreTags) { - valueByte = HAS_MORE_TAGS | valueLength; - } - else { - valueByte = valueLength; - } - byteBuf.writeByte(valueByte); - ByteBufUtil.reserveAndWriteUtf8(byteBuf, value, valueLength); - } - - return byteBuf; - } - - protected static void encodeBigInteger(ByteBuf byteBuf, BigInteger bigInteger) { - byte[] idBytes = bigInteger.toByteArray(); - // truncate or pad to 16 bytes or 128 bits - // byte[] normalizedBytes = Arrays.copyOf(idBytes, 16); - byte[] normalizedBytes = new byte[16]; - // right shift - int destPos = normalizedBytes.length - idBytes.length; - System.arraycopy(idBytes, 0, normalizedBytes, destPos, idBytes.length); - - byteBuf.writeBytes(normalizedBytes); - } - - protected static void encodeString(ByteBuf byteBuf, String s) { - int length = NumberUtils.requireUnsignedByte(ByteBufUtil.utf8Bytes(s)); - byteBuf.writeByte(length); - ByteBufUtil.reserveAndWriteUtf8(byteBuf, s, length); - } - - protected static TagsMetadata decode(ByteBuf byteBuf) { - AtomicInteger offset = new AtomicInteger(0); - return decode(offset, byteBuf); - } - - protected static TagsMetadata decode(AtomicInteger offset, ByteBuf byteBuf) { - - Builder builder = TagsMetadata.builder(); - - // this means we've reached the end of the buffer - if (offset.get() >= byteBuf.writerIndex()) { - return builder.build(); - } - - boolean hasMoreTags = true; - - while (hasMoreTags) { - int keyByte = byteBuf.getByte(offset.get()); - offset.addAndGet(Byte.BYTES); - - boolean isWellKnownTag = (keyByte & WELL_KNOWN_TAG) == WELL_KNOWN_TAG; - - int keyLength = keyByte & MAX_TAG_LENGTH; - - Key key; - if (isWellKnownTag) { - WellKnownKey wellKnownKey = WellKnownKey.fromIdentifier(keyLength); - key = new Key(wellKnownKey, null); - } - else { - String keyString = byteBuf.toString(offset.get(), keyLength, - StandardCharsets.UTF_8); - offset.addAndGet(keyLength); - key = new Key(null, keyString); - } - - int valueByte = byteBuf.getByte(offset.get()); - offset.addAndGet(Byte.BYTES); - - hasMoreTags = (valueByte & HAS_MORE_TAGS) == HAS_MORE_TAGS; - int valueLength = valueByte & MAX_TAG_LENGTH; - String value = byteBuf.toString(offset.get(), valueLength, - StandardCharsets.UTF_8); - offset.addAndGet(valueLength); - - builder.with(key, value); - } - - return builder.build(); - } - - protected static BigInteger decodeBigInteger(ByteBuf byteBuf, AtomicInteger offset) { - byte[] idBytes = new byte[16]; - byteBuf.getBytes(offset.get(), idBytes, 0, 16); - offset.getAndAdd(16); - return new BigInteger(idBytes); - } - - protected static long decodeLong(ByteBuf byteBuf, AtomicInteger offset) { - return byteBuf.getLong(offset.getAndAdd(8)); - } - - protected static String decodeString(ByteBuf byteBuf, AtomicInteger offset) { - int length = byteBuf.getByte(offset.get()); - int index = offset.addAndGet(Byte.BYTES); - String s = byteBuf.toString(index, length, StandardCharsets.UTF_8); - offset.addAndGet(length); - return s; - } - - public static class Builder { - - private final TagsMetadata metadata; - - public Builder() { - this.metadata = new TagsMetadata(new LinkedHashMap<>()); - } - - public Builder with(String key, String value) { - Assert.notNull(key, "key may not be null"); - return with(new Key(key), value); - } - - public Builder with(WellKnownKey key, String value) { - Assert.notNull(key, "key may not be null"); - return with(new Key(key), value); - } - - public Builder with(Key key, String value) { - Assert.notNull(key, "key may not be null"); - this.metadata.put(key, value); - return this; - } - - public Builder routeId(String routeId) { - Assert.notNull(routeId, "routeId may not be null"); - return with(ROUTE_ID, routeId); - } - - public Builder serviceName(String serviceName) { - Assert.notNull(serviceName, "serviceName may not be null"); - return with(SERVICE_NAME, serviceName); - } - - public Builder with(TagsMetadata tagsMetadata) { - this.metadata.getTags().putAll(tagsMetadata.getTags()); - return this; - } - - public TagsMetadata build() { - return this.metadata; - } - - public ByteBuf encode() { - return TagsMetadata.encode(build()); - } - - } - - public static class Key { - - private final WellKnownKey wellKnownKey; - - private final String key; - - public Key(WellKnownKey wellKnownKey) { - this(wellKnownKey, null); - } - - public Key(String key) { - this(null, key); - } - - public Key(WellKnownKey wellKnownKey, String key) { - this.wellKnownKey = wellKnownKey; - this.key = key; - } - - public WellKnownKey getWellKnownKey() { - return this.wellKnownKey; - } - - public String getKey() { - return this.key; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Key key1 = (Key) o; - return this.wellKnownKey == key1.wellKnownKey - && Objects.equals(this.key, key1.key); - } - - @Override - public int hashCode() { - return Objects.hash(this.wellKnownKey, this.key); - } - - @Override - public String toString() { - StringJoiner joiner = new StringJoiner(", ", "[", "]"); - if (wellKnownKey != null) { - joiner.add(wellKnownKey.toString()); - joiner.add(String.format("0x%02x", wellKnownKey.getIdentifier())); - } - if (key != null) { - joiner.add("'" + key + "'"); - } - return joiner.toString(); - } - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/WellKnownKey.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/WellKnownKey.java deleted file mode 100644 index c15d463a..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/java/org/springframework/cloud/gateway/rsocket/common/metadata/WellKnownKey.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -public enum WellKnownKey { - - // CHECKSTYLE:OFF - // @formatter:off - UNPARSEABLE_KEY("UNPARSEABLE_KEY_DO_NOT_USE", (byte) -2), - UNKNOWN_RESERVED_KEY("UNKNOWN_YET_RESERVED_DO_NOT_USE", (byte) -1), - - NO_TAG("NO_TAG_DO_NOT_USE", (byte) 0x00), - SERVICE_NAME("io.rsocket.routing.ServiceName", (byte) 0x01), - ROUTE_ID("io.rsocket.routing.RouteId", (byte) 0x02), - INSTANCE_NAME("io.rsocket.routing.InstanceName", (byte) 0x03), - CLUSTER_NAME("io.rsocket.routing.ClusterName", (byte) 0x04), - PROVIDER("io.rsocket.routing.Provider", (byte) 0x05), - REGION("io.rsocket.routing.Region", (byte) 0x06), - ZONE("io.rsocket.routing.Zone", (byte) 0x07), - DEVICE("io.rsocket.routing.Device", (byte) 0x08), - OS("io.rsocket.routing.OS", (byte) 0x09), - USER_NAME("io.rsocket.routing.UserName", (byte) 0x0A), - USER_ID("io.rsocket.routing.UserId", (byte) 0x0B), - MAJOR_VERSION("io.rsocket.routing.MajorVersion", (byte) 0x0C), - MINOR_VERSION("io.rsocket.routing.MinorVersion", (byte) 0x0D), - PATCH_VERSION("io.rsocket.routing.PatchVersion", (byte) 0x0E), - VERSION("io.rsocket.routing.Version", (byte) 0x0F), - ENVIRONMENT("io.rsocket.routing.Environment", (byte) 0x10), - TESTC_ELL("io.rsocket.routing.TestCell", (byte) 0x11), - DNS("io.rsocket.routing.DNS", (byte) 0x12), - IPV4("io.rsocket.routing.IPv4", (byte) 0x13), - IPV6("io.rsocket.routing.IPv6", (byte) 0x14), - COUNTRY("io.rsocket.routing.Country", (byte) 0x15), - TIME_ZONE("io.rsocket.routing.TimeZone", (byte) 0x1A), - SHARD_KEY("io.rsocket.routing.ShardKey", (byte) 0x1B), - SHARD_METHOD("io.rsocket.routing.ShardMethod", (byte) 0x1C), - STICKY_ROUTE_KEY("io.rsocket.routing.StickyRouteKey", (byte) 0x1D), - LB_METHOD("io.rsocket.routing.LBMethod", (byte) 0x1E), - BROKER_EXTENSION("Broker Implementation Extension Key", (byte) 0x1E), - WELL_KNOWN_EXTENSION("Well Known Extension Key", (byte) 0x1E); - // @formatter:on - // CHECKSTYLE:ON - - static final WellKnownKey[] TYPES_BY_ID; - static final Map TYPES_BY_STRING; - - static { - // precompute an array of all valid mime ids, - // filling the blanks with the RESERVED enum - TYPES_BY_ID = new WellKnownKey[128]; // 0-127 inclusive - Arrays.fill(TYPES_BY_ID, UNKNOWN_RESERVED_KEY); - // also prepare a Map of the types by key string - TYPES_BY_STRING = new HashMap<>(128); - - for (WellKnownKey value : values()) { - if (value.getIdentifier() >= 0) { - TYPES_BY_ID[value.getIdentifier()] = value; - TYPES_BY_STRING.put(value.getString(), value); - } - } - } - - private final byte identifier; - - private final String str; - - WellKnownKey(String str, byte identifier) { - this.str = str; - this.identifier = identifier; - } - - public static WellKnownKey fromIdentifier(int id) { - if (id < 0x00 || id > 0x7F) { - return UNPARSEABLE_KEY; - } - return TYPES_BY_ID[id]; - } - - public static WellKnownKey fromMimeType(String mimeType) { - if (mimeType == null) { - throw new IllegalArgumentException("type must be non-null"); - } - - // force UNPARSEABLE if by chance UNKNOWN_RESERVED_MIME_TYPE's text has been used - if (mimeType.equals(UNKNOWN_RESERVED_KEY.str)) { - return UNPARSEABLE_KEY; - } - - return TYPES_BY_STRING.getOrDefault(mimeType, UNPARSEABLE_KEY); - } - - /** - * @return the byte identifier of the mime type, guaranteed to be positive or zero. - */ - public byte getIdentifier() { - return identifier; - } - - /** - * @return the mime type represented as a {@link String}, which is made of US_ASCII - * compatible characters only - */ - public String getString() { - return str; - } - - /** @see #getString() */ - @Override - public String toString() { - return str; - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/resources/META-INF/spring.factories b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 530d8e7c..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,4 +0,0 @@ -# Auto Configure -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.gateway.rsocket.common.autoconfigure.GatewayRSocketCommonAutoConfiguration,\ -org.springframework.cloud.gateway.rsocket.common.autoconfigure.GatewayRSocketCommonMetadataAutoConfiguration diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/ForwardingIntegrationTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/ForwardingIntegrationTests.java deleted file mode 100644 index 68d08138..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/ForwardingIntegrationTests.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import java.util.Map; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.rsocket.Payload; -import io.rsocket.util.DefaultPayload; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.gateway.rsocket.common.test.MetadataEncoder; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.messaging.rsocket.MetadataExtractor; -import org.springframework.messaging.rsocket.RSocketStrategies; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - -@RunWith(SpringRunner.class) -@SpringBootTest(properties = "spring.rsocket.server.port=0", webEnvironment = RANDOM_PORT) -public class ForwardingIntegrationTests extends ForwardingTests { - - @Autowired - private RSocketStrategies strategies; - - @Override - protected ByteBuf encode(Forwarding forwarding) { - DataBuffer dataBuffer = new MetadataEncoder(Metadata.COMPOSITE_MIME_TYPE, - strategies).metadata(forwarding, Forwarding.FORWARDING_MIME_TYPE) - .encode(); - return TagsMetadata.asByteBuf(dataBuffer); - } - - @Override - protected Forwarding decode(ByteBuf byteBuf) { - MetadataExtractor metadataExtractor = strategies.metadataExtractor(); - Payload payload = DefaultPayload.create(Unpooled.EMPTY_BUFFER, byteBuf); - Map metadata = metadataExtractor.extract(payload, - Metadata.COMPOSITE_MIME_TYPE); - assertThat(metadata).containsKey(Forwarding.METADATA_KEY); - - return (Forwarding) metadata.get(Forwarding.METADATA_KEY); - } - - @SpringBootConfiguration - @EnableAutoConfiguration - static class Config { - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/ForwardingTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/ForwardingTests.java deleted file mode 100644 index 399bb425..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/ForwardingTests.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import java.math.BigInteger; -import java.util.LinkedHashMap; - -import io.netty.buffer.ByteBuf; -import org.junit.Test; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata.Key; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetupTests.MAX_BIGINT; -import static org.springframework.cloud.gateway.rsocket.common.metadata.RouteSetupTests.TWO_BYTE_BIGINT; -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.REGION; - -public class ForwardingTests { - - @Test - public void encodeAndDecodeWorksMaxBigint() { - ByteBuf byteBuf = createForwarding(MAX_BIGINT); - assertForwarding(byteBuf, MAX_BIGINT); - } - - @Test - public void encodeAndDecodeWorksMinBigint() { - ByteBuf byteBuf = createForwarding(BigInteger.ONE); - assertForwarding(byteBuf, BigInteger.ONE); - } - - @Test - public void encodeAndDecodeWorksTwoBytes() { - ByteBuf byteBuf = createForwarding(TWO_BYTE_BIGINT); - assertForwarding(byteBuf, TWO_BYTE_BIGINT); - } - - protected ByteBuf createForwarding(BigInteger originRouteId) { - LinkedHashMap tags = new LinkedHashMap<>(); - Forwarding forwarding = Forwarding.of(originRouteId).with(REGION, "us-east-1") - .build(); - return encode(forwarding); - } - - protected ByteBuf encode(Forwarding forwarding) { - return forwarding.encode(); - } - - protected void assertForwarding(ByteBuf byteBuf, BigInteger originRouteId) { - Forwarding forwarding = decode(byteBuf); - assertThat(forwarding).isNotNull(); - assertThat(forwarding.getOriginRouteId()).isEqualTo(originRouteId); - assertThat(forwarding.getTags()).hasSize(1).containsOnlyKeys(new Key(REGION)) - .containsValues("us-east-1"); - } - - protected Forwarding decode(ByteBuf byteBuf) { - return Forwarding.decodeForwarding(byteBuf); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetupIntegrationTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetupIntegrationTests.java deleted file mode 100644 index 02323024..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetupIntegrationTests.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import java.util.Map; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.rsocket.Payload; -import io.rsocket.util.DefaultPayload; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cloud.gateway.rsocket.common.test.MetadataEncoder; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.messaging.rsocket.MetadataExtractor; -import org.springframework.messaging.rsocket.RSocketStrategies; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - -@RunWith(SpringRunner.class) -@SpringBootTest(properties = "spring.rsocket.server.port=0", webEnvironment = RANDOM_PORT) -public class RouteSetupIntegrationTests extends RouteSetupTests { - - @Autowired - private RSocketStrategies strategies; - - @Override - protected ByteBuf encode(RouteSetup routeSetup) { - DataBuffer dataBuffer = new MetadataEncoder(Metadata.COMPOSITE_MIME_TYPE, - strategies).metadata(routeSetup, RouteSetup.ROUTE_SETUP_MIME_TYPE) - .encode(); - return TagsMetadata.asByteBuf(dataBuffer); - } - - @Override - protected RouteSetup decode(ByteBuf byteBuf) { - MetadataExtractor metadataExtractor = strategies.metadataExtractor(); - Payload payload = DefaultPayload.create(Unpooled.EMPTY_BUFFER, byteBuf); - Map metadata = metadataExtractor.extract(payload, - Metadata.COMPOSITE_MIME_TYPE); - assertThat(metadata).containsKey(RouteSetup.METADATA_KEY); - - return (RouteSetup) metadata.get(RouteSetup.METADATA_KEY); - } - - @SpringBootConfiguration - @EnableAutoConfiguration - static class Config { - - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetupTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetupTests.java deleted file mode 100644 index fc29026a..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/RouteSetupTests.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import java.math.BigInteger; - -import io.netty.buffer.ByteBuf; -import org.junit.Test; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata.Key; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.REGION; - -public class RouteSetupTests { - - static final BigInteger MAX_BIGINT = new BigInteger( - "170141183460469231731687303715884105727"); - static final BigInteger TWO_BYTE_BIGINT = new BigInteger("128"); - - @Test - public void bigIntegerTest() { - byte[] bytes = MAX_BIGINT.toByteArray(); - System.out.println("max bytes: " + bytes.length); - - bytes = BigInteger.ONE.toByteArray(); - System.out.println("min bytes: " + bytes.length); - - BigInteger bigInteger = TWO_BYTE_BIGINT; - bytes = bigInteger.toByteArray(); - System.out.println("16 bytes: " + bytes.length); - } - - @Test - public void encodeAndDecodeWorksMaxBigint() { - ByteBuf byteBuf = createRouteSetup(MAX_BIGINT); - assertRouteSetup(byteBuf, MAX_BIGINT); - } - - @Test - public void encodeAndDecodeWorksMinBigint() { - ByteBuf byteBuf = createRouteSetup(BigInteger.ONE); - assertRouteSetup(byteBuf, BigInteger.ONE); - } - - @Test - public void encodeAndDecodeWorksTwoBytes() { - ByteBuf byteBuf = createRouteSetup(TWO_BYTE_BIGINT); - assertRouteSetup(byteBuf, TWO_BYTE_BIGINT); - } - - @Test - public void encodeAndDecodeWorksEmptyTags() { - ByteBuf byteBuf = createRouteSetup(TWO_BYTE_BIGINT, false); - assertRouteSetup(byteBuf, TWO_BYTE_BIGINT, false); - } - - protected ByteBuf createRouteSetup(BigInteger id) { - return createRouteSetup(id, true); - } - - protected ByteBuf createRouteSetup(BigInteger id, boolean addTags) { - RouteSetup.Builder routeSetup = RouteSetup.of(id, "myservice11111111"); - if (addTags) { - routeSetup.with(REGION, "us-east-1"); - } - return encode(routeSetup.build()); - } - - protected ByteBuf encode(RouteSetup routeSetup) { - return routeSetup.encode(); - } - - protected void assertRouteSetup(ByteBuf byteBuf, BigInteger routeId) { - assertRouteSetup(byteBuf, routeId, true); - } - - protected void assertRouteSetup(ByteBuf byteBuf, BigInteger routeId, - boolean addTags) { - RouteSetup routeSetup = decode(byteBuf); - assertThat(routeSetup).isNotNull(); - assertThat(routeSetup.getId()).isEqualTo(routeId); - assertThat(routeSetup.getServiceName()).isEqualTo("myservice11111111"); - if (addTags) { - assertThat(routeSetup.getTags()).hasSize(1).containsOnlyKeys(new Key(REGION)) - .containsValues("us-east-1"); - } - else { - assertThat(routeSetup.getTags()).isEmpty(); - } - } - - protected RouteSetup decode(ByteBuf byteBuf) { - return RouteSetup.decodeRouteSetup(byteBuf); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/TagsMetadataTests.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/TagsMetadataTests.java deleted file mode 100644 index e32fe29d..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/metadata/TagsMetadataTests.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.metadata; - -import io.netty.buffer.ByteBuf; -import org.junit.Test; - -import org.springframework.cloud.gateway.rsocket.common.metadata.TagsMetadata.Key; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.ROUTE_ID; -import static org.springframework.cloud.gateway.rsocket.common.metadata.WellKnownKey.SERVICE_NAME; - -public class TagsMetadataTests { - - @Test - public void encodeAndDecodeWorksAllWellKnowKeys() { - ByteBuf byteBuf = TagsMetadata.builder().with(ROUTE_ID, "routeId1111111") - .with(SERVICE_NAME, "serviceName2222222").encode(); - TagsMetadata metadata = TagsMetadata.decode(byteBuf); - assertThat(metadata).isNotNull(); - assertThat(metadata.getTags()).hasSize(2) - .containsOnlyKeys(new Key(ROUTE_ID), new Key(SERVICE_NAME)) - .containsValues("routeId1111111", "serviceName2222222"); - } - - @Test - public void encodeAndDecodeWorksAllStringKeys() { - ByteBuf byteBuf = TagsMetadata.builder().with("mykey111111111", "myval1111111") - .with("mykey2222222222", "myval2222222").encode(); - TagsMetadata metadata = TagsMetadata.decode(byteBuf); - assertThat(metadata).isNotNull(); - assertThat(metadata.getTags()).hasSize(2) - .containsOnlyKeys(new Key("mykey111111111"), new Key("mykey2222222222")) - .containsValues("myval1111111", "myval2222222"); - } - - @Test - public void encodeAndDecodeWorksMixedKeys() { - ByteBuf byteBuf = TagsMetadata.builder().with(ROUTE_ID, "routeId1111111") - .with("mykey2222222222", "myval2222222").encode(); - TagsMetadata metadata = TagsMetadata.decode(byteBuf); - assertThat(metadata).isNotNull(); - assertThat(metadata.getTags()).hasSize(2) - .containsOnlyKeys(new Key(ROUTE_ID), new Key("mykey2222222222")) - .containsValues("routeId1111111", "myval2222222"); - } - -} diff --git a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/test/MetadataEncoder.java b/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/test/MetadataEncoder.java deleted file mode 100644 index 1bffed2b..00000000 --- a/spring-cloud-gateway-rsocket/spring-cloud-gateway-rsocket-common/src/test/java/org/springframework/cloud/gateway/rsocket/common/test/MetadataEncoder.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed 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 - * - * https://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 org.springframework.cloud.gateway.rsocket.common.test; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.CompositeByteBuf; -import io.netty.buffer.Unpooled; -import io.rsocket.metadata.CompositeMetadataFlyweight; -import io.rsocket.metadata.TaggingMetadataFlyweight; -import io.rsocket.metadata.WellKnownMimeType; - -import org.springframework.core.ResolvableType; -import org.springframework.core.codec.Encoder; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.core.io.buffer.NettyDataBuffer; -import org.springframework.core.io.buffer.NettyDataBufferFactory; -import org.springframework.lang.Nullable; -import org.springframework.messaging.rsocket.MetadataExtractor; -import org.springframework.messaging.rsocket.PayloadUtils; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.messaging.rsocket.RSocketStrategies; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; -import org.springframework.util.MimeType; -import org.springframework.util.ObjectUtils; - -/** - * Helps to collect metadata values and mime types, and encode them. TODO: remove if - * framework class is made public. - * - * {@link MetadataExtractor} original. - * - * @author Rossen Stoyanchev - */ -public class MetadataEncoder { - - /** For route variable replacement. */ - private static final Pattern VARS_PATTERN = Pattern.compile("\\{([^/]+?)}"); - - private final MimeType metadataMimeType; - - private final RSocketStrategies strategies; - - private final boolean isComposite; - - private final ByteBufAllocator allocator; - - @Nullable - private String route; - - private final Map metadata = new LinkedHashMap<>(4); - - public MetadataEncoder(MimeType metadataMimeType, RSocketStrategies strategies) { - Assert.notNull(metadataMimeType, "'metadataMimeType' is required"); - Assert.notNull(strategies, "RSocketStrategies is required"); - this.metadataMimeType = metadataMimeType; - this.strategies = strategies; - this.isComposite = this.metadataMimeType.toString() - .equals(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()); - this.allocator = bufferFactory() instanceof NettyDataBufferFactory - ? ((NettyDataBufferFactory) bufferFactory()).getByteBufAllocator() - : ByteBufAllocator.DEFAULT; - } - - private DataBufferFactory bufferFactory() { - return this.strategies.dataBufferFactory(); - } - - /** - * Set the route to a remote handler as described in - * {@link RSocketRequester#route(String, Object...)}. - */ - public MetadataEncoder route(String route, Object... routeVars) { - this.route = expand(route, routeVars); - assertMetadataEntryCount(); - return this; - } - - private static String expand(String route, Object... routeVars) { - if (ObjectUtils.isEmpty(routeVars)) { - return route; - } - StringBuffer sb = new StringBuffer(); - int index = 0; - Matcher matcher = VARS_PATTERN.matcher(route); - while (matcher.find()) { - Assert.isTrue(index < routeVars.length, - () -> "No value for variable '" + matcher.group(1) + "'"); - String value = routeVars[index].toString(); - value = value.contains(".") ? value.replaceAll("\\.", "%2E") : value; - matcher.appendReplacement(sb, value); - index++; - } - return sb.toString(); - } - - private void assertMetadataEntryCount() { - if (!this.isComposite) { - int count = this.route != null ? this.metadata.size() + 1 - : this.metadata.size(); - Assert.isTrue(count < 2, - "Composite metadata required for multiple metadata entries."); - } - } - - /** - * Add a metadata entry. If called more than once or in addition to route, composite - * metadata must be in use. - */ - public MetadataEncoder metadata(Object metadata, @Nullable MimeType mimeType) { - if (this.isComposite) { - Assert.notNull(mimeType, - "MimeType is required for composite metadata entries."); - } - else if (mimeType == null) { - mimeType = this.metadataMimeType; - } - else if (!this.metadataMimeType.equals(mimeType)) { - throw new IllegalArgumentException("Mime type is optional (may be null) " - + "but was provided and does not match the connection metadata mime type."); - } - this.metadata.put(metadata, mimeType); - assertMetadataEntryCount(); - return this; - } - - /** - * Add route and/or metadata, both optional. - */ - public MetadataEncoder metadataAndOrRoute(@Nullable Map metadata, - @Nullable String route, @Nullable Object[] vars) { - - if (route != null) { - this.route = expand(route, vars != null ? vars : new Object[0]); - } - if (!CollectionUtils.isEmpty(metadata)) { - for (Map.Entry entry : metadata.entrySet()) { - metadata(entry.getKey(), entry.getValue()); - } - } - assertMetadataEntryCount(); - return this; - } - - /** - * Encode the collected metadata entries to a {@code DataBuffer}. - * @see PayloadUtils#createPayload(DataBuffer, DataBuffer) - */ - public DataBuffer encode() { - if (this.isComposite) { - CompositeByteBuf composite = this.allocator.compositeBuffer(); - try { - if (this.route != null) { - CompositeMetadataFlyweight.encodeAndAddMetadata(composite, - this.allocator, WellKnownMimeType.MESSAGE_RSOCKET_ROUTING, - encodeRoute()); - } - this.metadata.forEach((value, mimeType) -> { - ByteBuf metadata = (value instanceof ByteBuf ? (ByteBuf) value - : asByteBuf(encodeEntry(value, mimeType))); - CompositeMetadataFlyweight.encodeAndAddMetadata(composite, - this.allocator, mimeType.toString(), metadata); - }); - return asDataBuffer(composite); - } - catch (Throwable ex) { - composite.release(); - throw ex; - } - } - else if (this.route != null) { - Assert.isTrue(this.metadata.isEmpty(), - "Composite metadata required for route and other entries"); - String routingMimeType = WellKnownMimeType.MESSAGE_RSOCKET_ROUTING - .getString(); - return this.metadataMimeType.toString().equals(routingMimeType) - ? asDataBuffer(encodeRoute()) - : encodeEntry(this.route, this.metadataMimeType); - } - else { - Assert.isTrue(this.metadata.size() == 1, - "Composite metadata required for multiple entries"); - Map.Entry entry = this.metadata.entrySet().iterator() - .next(); - if (!this.metadataMimeType.equals(entry.getValue())) { - throw new IllegalArgumentException( - "Connection configured for metadata mime type " + "'" - + this.metadataMimeType + "', but actual is `" - + this.metadata + "`"); - } - return encodeEntry(entry.getKey(), entry.getValue()); - } - } - - private ByteBuf encodeRoute() { - return TaggingMetadataFlyweight.createRoutingMetadata(this.allocator, - Collections.singletonList(this.route)).getContent(); - } - - @SuppressWarnings("unchecked") - private DataBuffer encodeEntry(Object metadata, MimeType mimeType) { - if (metadata instanceof ByteBuf) { - return asDataBuffer((ByteBuf) metadata); - } - ResolvableType type = ResolvableType.forInstance(metadata); - Encoder encoder = this.strategies.encoder(type, mimeType); - Assert.notNull(encoder, () -> "No encoder for metadata " + metadata - + ", mimeType '" + mimeType + "'"); - return encoder.encodeValue((T) metadata, bufferFactory(), type, mimeType, - Collections.emptyMap()); - } - - private DataBuffer asDataBuffer(ByteBuf byteBuf) { - if (bufferFactory() instanceof NettyDataBufferFactory) { - return ((NettyDataBufferFactory) bufferFactory()).wrap(byteBuf); - } - else { - DataBuffer buffer = bufferFactory().wrap(byteBuf.nioBuffer()); - byteBuf.release(); - return buffer; - } - } - - public static DataBuffer emptyDataBuffer(RSocketStrategies rSocketStrategies) { - return rSocketStrategies.dataBufferFactory().wrap(new byte[0]); - } - - static ByteBuf asByteBuf(DataBuffer buffer) { - return buffer instanceof NettyDataBuffer - ? ((NettyDataBuffer) buffer).getNativeBuffer() - : Unpooled.wrappedBuffer(buffer.asByteBuffer()); - } - -}