This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push:
new 92a8490 [SCB-2218] allow edge invocation process by filter (#2297)
92a8490 is described below
commit 92a8490b661c86637cf7cb7e04b14231863dec27
Author: wujimin <[email protected]>
AuthorDate: Thu Mar 18 20:25:25 2021 +0800
[SCB-2218] allow edge invocation process by filter (#2297)
---
.../common/rest/RestProducerInvocationCreator.java | 32 +++++---
.../rest/RestVertxProducerInvocationCreator.java | 2 +-
.../rest/filter/inner/RestServerCodecFilter.java | 15 ++--
.../rest/RestProducerInvocationCreatorTest.java | 10 +--
.../filter/inner/RestServerCodecFilterTest.java | 6 +-
.../org/apache/servicecomb/core/Invocation.java | 4 +
.../core/invocation/InvocationCreator.java | 4 +-
.../core/invocation/ProducerInvocationFlow.java | 6 +-
.../invocation/ProducerInvocationFlowTest.java | 11 +--
.../edge/core/CompatiblePathVersionMapper.java | 4 +-
.../edge/core/DefaultEdgeDispatcher.java | 75 ++++++++++++++---
.../edge/core/EdgeAddHeaderClientFilter.java | 34 +++++---
.../servicecomb/edge/core/EdgeAddHeaderFilter.java | 54 ++++++++++++
.../edge/core/EdgeInvocationCreator.java | 96 ++++++++++++++++++++++
.../edge/core/EdgeRestTransportClient.java | 13 +--
.../edge/core/EdgeServerCodecFilter.java | 66 +++++++++++++++
.../edge/core/TestDefaultEdgeDispatcher.java | 25 +++---
.../it-edge/src/main/resources/microservice.yaml | 6 ++
.../servicecomb/registry/lightweight/Self.java | 8 +-
.../transport/highway/HighwayServerConnection.java | 6 +-
.../transport/rest/vertx/RestServerVerticle.java | 6 +-
.../transport/rest/vertx/VertxHttpDispatcher.java | 8 +-
22 files changed, 397 insertions(+), 94 deletions(-)
diff --git
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreator.java
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreator.java
index 69eb467..0cbdc15 100644
---
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreator.java
+++
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreator.java
@@ -22,6 +22,7 @@ import static
org.apache.servicecomb.core.exception.ExceptionCodes.GENERIC_CLIEN
import static
org.apache.servicecomb.core.exception.ExceptionCodes.NOT_DEFINED_ANY_SCHEMA;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
import javax.ws.rs.core.HttpHeaders;
@@ -48,7 +49,7 @@ import io.vertx.core.json.Json;
public abstract class RestProducerInvocationCreator implements
InvocationCreator {
private static final Logger LOGGER =
LoggerFactory.getLogger(RestVertxProducerInvocationCreator.class);
- protected final MicroserviceMeta microserviceMeta;
+ protected MicroserviceMeta microserviceMeta;
protected final Endpoint endpoint;
@@ -56,11 +57,11 @@ public abstract class RestProducerInvocationCreator
implements InvocationCreator
protected final HttpServletResponseEx responseEx;
- private RestOperationMeta restOperationMeta;
+ protected RestOperationMeta restOperationMeta;
protected ProduceProcessor produceProcessor;
- public RestProducerInvocationCreator(@Nonnull MicroserviceMeta
microserviceMeta, @Nonnull Endpoint endpoint,
+ public RestProducerInvocationCreator(MicroserviceMeta microserviceMeta,
Endpoint endpoint,
@Nonnull HttpServletRequestEx requestEx, @Nonnull HttpServletResponseEx
responseEx) {
this.microserviceMeta = microserviceMeta;
this.endpoint = endpoint;
@@ -69,12 +70,10 @@ public abstract class RestProducerInvocationCreator
implements InvocationCreator
}
@Override
- public Invocation create() {
+ public CompletableFuture<Invocation> createAsync() {
initRestOperation();
- Invocation invocation = InvocationFactory.forProvider(endpoint,
- restOperationMeta.getOperationMeta(),
- null);
+ Invocation invocation = createInstance();
initInvocationContext(invocation);
initProduceProcessor();
@@ -82,7 +81,11 @@ public abstract class RestProducerInvocationCreator
implements InvocationCreator
invocation.addLocalContext(RestConst.REST_REQUEST, requestEx);
- return invocation;
+ return CompletableFuture.completedFuture(invocation);
+ }
+
+ protected Invocation createInstance() {
+ return InvocationFactory.forProvider(endpoint,
restOperationMeta.getOperationMeta(), null);
}
protected void initInvocationContext(Invocation invocation) {
@@ -98,19 +101,24 @@ public abstract class RestProducerInvocationCreator
implements InvocationCreator
protected abstract void initTransportContext(Invocation invocation);
- private void initRestOperation() {
- OperationLocator locator = locateOperation();
+ protected void initRestOperation() {
+ OperationLocator locator = locateOperation(microserviceMeta);
requestEx.setAttribute(RestConst.PATH_PARAMETERS, locator.getPathVarMap());
restOperationMeta = locator.getOperation();
}
- private OperationLocator locateOperation() {
+ protected OperationLocator locateOperation(MicroserviceMeta
microserviceMeta) {
ServicePathManager servicePathManager =
ServicePathManager.getServicePathManager(microserviceMeta);
if (servicePathManager == null) {
- LOGGER.error("No schema defined for {}:{}.",
microserviceMeta.getAppId(), microserviceMeta.getMicroserviceName());
+ LOGGER.error("No schema defined for {}:{}.",
this.microserviceMeta.getAppId(),
+ this.microserviceMeta.getMicroserviceName());
throw Exceptions.create(NOT_FOUND, NOT_DEFINED_ANY_SCHEMA,
NOT_FOUND.getReasonPhrase());
}
+ return locateOperation(servicePathManager);
+ }
+
+ protected OperationLocator locateOperation(ServicePathManager
servicePathManager) {
return
servicePathManager.producerLocateOperation(requestEx.getRequestURI(),
requestEx.getMethod());
}
diff --git
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestVertxProducerInvocationCreator.java
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestVertxProducerInvocationCreator.java
index 4f12dea..fcae4c7 100644
---
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestVertxProducerInvocationCreator.java
+++
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestVertxProducerInvocationCreator.java
@@ -30,7 +30,7 @@ public class RestVertxProducerInvocationCreator extends
RestProducerInvocationCr
private final RoutingContext routingContext;
public RestVertxProducerInvocationCreator(@Nonnull RoutingContext
routingContext,
- @Nonnull MicroserviceMeta microserviceMeta, @Nonnull Endpoint endpoint,
+ MicroserviceMeta microserviceMeta, Endpoint endpoint,
@Nonnull HttpServletRequestEx requestEx, @Nonnull HttpServletResponseEx
responseEx) {
super(microserviceMeta, endpoint, requestEx, responseEx);
this.routingContext = routingContext;
diff --git
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java
index 3dd5557..9d8894b 100644
---
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java
+++
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java
@@ -61,22 +61,25 @@ public class RestServerCodecFilter implements
ProducerFilter {
@Override
public CompletableFuture<Response> onFilter(Invocation invocation,
FilterNode nextNode) {
return CompletableFuture.completedFuture(invocation)
- .thenCompose(this::decodeRequest)
- .thenCompose(nextNode::onFilter)
+ .thenAccept(this::decodeRequest)
+ .thenCompose(v -> invokeNext(invocation, nextNode))
.exceptionally(exception -> exceptionToResponse(invocation, exception,
INTERNAL_SERVER_ERROR))
.thenCompose(response -> encodeResponse(invocation, response));
}
- protected CompletableFuture<Invocation> decodeRequest(Invocation invocation)
{
- HttpTransportContext transportContext = invocation.getTransportContext();
- HttpServletRequestEx requestEx = transportContext.getRequestEx();
+ protected CompletableFuture<Response> invokeNext(Invocation invocation,
FilterNode nextNode) {
+ return nextNode.onFilter(invocation);
+ }
+
+ protected Void decodeRequest(Invocation invocation) {
+ HttpServletRequestEx requestEx = invocation.getRequestEx();
OperationMeta operationMeta = invocation.getOperationMeta();
RestOperationMeta restOperationMeta =
operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION);
Map<String, Object> swaggerArguments = RestCodec.restToArgs(requestEx,
restOperationMeta);
invocation.setSwaggerArguments(swaggerArguments);
- return CompletableFuture.completedFuture(invocation);
+ return null;
}
protected CompletableFuture<Response> encodeResponse(Invocation invocation,
Response response) {
diff --git
a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreatorTest.java
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreatorTest.java
index b1dc7ff..f8159a6 100644
---
a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreatorTest.java
+++
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreatorTest.java
@@ -115,7 +115,7 @@ public class RestProducerInvocationCreatorTest {
public void should_failed_when_not_defined_any_schema() {
mockGetServicePathManager(null);
- InvocationException throwable = (InvocationException) catchThrowable(() ->
creator.create());
+ InvocationException throwable = (InvocationException) catchThrowable(() ->
creator.createAsync().join());
CommonExceptionData data = (CommonExceptionData) throwable.getErrorData();
assertThat(throwable.getStatusCode()).isEqualTo(NOT_FOUND.getStatusCode());
@@ -135,7 +135,7 @@ public class RestProducerInvocationCreatorTest {
}
};
- InvocationException throwable = (InvocationException) catchThrowable(() ->
creator.create());
+ InvocationException throwable = (InvocationException) catchThrowable(() ->
creator.createAsync().join());
CommonExceptionData data = (CommonExceptionData) throwable.getErrorData();
assertThat(throwable.getStatusCode()).isEqualTo(NOT_ACCEPTABLE.getStatusCode());
@@ -147,7 +147,7 @@ public class RestProducerInvocationCreatorTest {
public void should_save_requestEx_in_invocation_context() {
mockGetServicePathManager();
- Invocation invocation = creator.create();
+ Invocation invocation = creator.createAsync().join();
Object request = invocation.getLocalContext(RestConst.REST_REQUEST);
assertThat(request).isSameAs(requestEx);
@@ -157,7 +157,7 @@ public class RestProducerInvocationCreatorTest {
public void should_save_path_var_map_in_requestEx() {
mockGetServicePathManager();
- creator.create();
+ creator.createAsync().join();
new Verifications() {
{
@@ -177,7 +177,7 @@ public class RestProducerInvocationCreatorTest {
}
};
- Invocation invocation = creator.create();
+ Invocation invocation = creator.createAsync().join();
assertThat(invocation.getContext("k")).isEqualTo("v");
}
diff --git
a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilterTest.java
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilterTest.java
index 8b887b6..24942a0 100644
---
a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilterTest.java
+++
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilterTest.java
@@ -112,8 +112,8 @@ public class RestServerCodecFilterTest {
invocation.getTransportContext();
result = transportContext;
- transportContext.getRequestEx();
- result = new RuntimeExceptionWithoutStackTrace("encode request
failed");
+ invocation.getRequestEx();
+ result = new RuntimeExceptionWithoutStackTrace("mock encode request
failed");
}
};
}
@@ -147,7 +147,7 @@ public class RestServerCodecFilterTest {
assertThat(response.getStatus()).isEqualTo(INTERNAL_SERVER_ERROR);
assertThat(Json.encode(response.getResult()))
- .isEqualTo("{\"code\":\"SCB.50000000\",\"message\":\"encode request
failed\"}");
+ .isEqualTo("{\"code\":\"SCB.50000000\",\"message\":\"mock encode
request failed\"}");
}
private void success_invocation() throws InterruptedException,
ExecutionException {
diff --git a/core/src/main/java/org/apache/servicecomb/core/Invocation.java
b/core/src/main/java/org/apache/servicecomb/core/Invocation.java
index ae35727..88f42bc 100644
--- a/core/src/main/java/org/apache/servicecomb/core/Invocation.java
+++ b/core/src/main/java/org/apache/servicecomb/core/Invocation.java
@@ -458,6 +458,10 @@ public class Invocation extends SwaggerInvocation {
return InvocationType.CONSUMER.equals(invocationType);
}
+ public boolean isProducer() {
+ return InvocationType.PRODUCER.equals(invocationType);
+ }
+
public boolean isEdge() {
return edge;
}
diff --git
a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationCreator.java
b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationCreator.java
index 5b86c3b..a413fce 100644
---
a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationCreator.java
+++
b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationCreator.java
@@ -16,11 +16,13 @@
*/
package org.apache.servicecomb.core.invocation;
+import java.util.concurrent.CompletableFuture;
+
import org.apache.servicecomb.core.Invocation;
/**
* better to named InvocationFactory, but already be used by old version
*/
public interface InvocationCreator {
- Invocation create();
+ CompletableFuture<Invocation> createAsync();
}
diff --git
a/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java
b/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java
index 93af06c..6f4f8e2 100644
---
a/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java
+++
b/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java
@@ -16,9 +16,10 @@
*/
package org.apache.servicecomb.core.invocation;
+import java.util.concurrent.CompletableFuture;
+
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.core.exception.Exceptions;
-import org.apache.servicecomb.foundation.common.utils.AsyncUtils;
import org.apache.servicecomb.foundation.common.utils.ExceptionUtils;
import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
@@ -49,7 +50,8 @@ public abstract class ProducerInvocationFlow {
}
public void run() {
- AsyncUtils.tryCatchSupplier(invocationCreator::create)
+ CompletableFuture.completedFuture(null)
+ .thenCompose(v -> invocationCreator.createAsync())
.exceptionally(this::sendCreateInvocationException)
.thenAccept(this::tryRunInvocation);
}
diff --git
a/core/src/test/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlowTest.java
b/core/src/test/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlowTest.java
index b8c0d46..f1d3ef7 100644
---
a/core/src/test/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlowTest.java
+++
b/core/src/test/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlowTest.java
@@ -17,6 +17,7 @@
package org.apache.servicecomb.core.invocation;
+import static java.util.concurrent.CompletableFuture.completedFuture;
import static org.assertj.core.api.Assertions.assertThat;
import org.apache.servicecomb.core.Invocation;
@@ -87,7 +88,7 @@ public class ProducerInvocationFlowTest {
@Test
public void should_start_invocation_when_succeed_to_create_invocation() {
mockFilterChain();
- TestFlow flow = new TestFlow(() -> invocation);
+ TestFlow flow = new TestFlow(() -> completedFuture(invocation));
flow.run();
@@ -102,7 +103,7 @@ public class ProducerInvocationFlowTest {
@Test
public void should_send_response_when_invocation_success() {
mockFilterChain();
- TestFlow flow = new TestFlow(() -> invocation);
+ TestFlow flow = new TestFlow(() -> completedFuture(invocation));
flow.run();
@@ -112,7 +113,7 @@ public class ProducerInvocationFlowTest {
@Test
public void should_finish_invocation_when_invocation_success() {
mockFilterChain();
- TestFlow flow = new TestFlow(() -> invocation);
+ TestFlow flow = new TestFlow(() -> completedFuture(invocation));
flow.run();
@@ -134,7 +135,7 @@ public class ProducerInvocationFlowTest {
@Test
public void should_send_response_when_invocation_fail() {
mockInvocationFailed();
- TestFlow flow = new TestFlow(() -> invocation);
+ TestFlow flow = new TestFlow(() -> completedFuture(invocation));
flow.run();
@@ -144,7 +145,7 @@ public class ProducerInvocationFlowTest {
@Test
public void should_finish_invocation_when_invocation_fail() {
mockInvocationFailed();
- TestFlow flow = new TestFlow(() -> invocation);
+ TestFlow flow = new TestFlow(() -> completedFuture(invocation));
flow.run();
diff --git
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CompatiblePathVersionMapper.java
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CompatiblePathVersionMapper.java
index 599bc32..cb92aec 100644
---
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CompatiblePathVersionMapper.java
+++
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CompatiblePathVersionMapper.java
@@ -31,9 +31,7 @@ public class CompatiblePathVersionMapper {
private Map<String, VersionRule> mapper = new ConcurrentHashMapEx<>();
public VersionRule getOrCreate(String pathVersion) {
- return mapper.computeIfAbsent(pathVersion, pv -> {
- return createVersionRule(pathVersion);
- });
+ return mapper.computeIfAbsent(pathVersion, this::createVersionRule);
}
// v + number
diff --git
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java
index 19f9f65..e85fb28 100644
---
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java
+++
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java
@@ -17,10 +17,19 @@
package org.apache.servicecomb.edge.core;
-import java.util.Map;
-
+import org.apache.servicecomb.common.rest.RestProducerInvocationFlow;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.invocation.InvocationCreator;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
+import
org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest;
+import
org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse;
+import org.apache.servicecomb.registry.definition.DefinitionConst;
+
+import com.google.common.annotations.VisibleForTesting;
import com.netflix.config.DynamicPropertyFactory;
+import io.vertx.codegen.annotations.Nullable;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
@@ -28,6 +37,7 @@ import io.vertx.ext.web.RoutingContext;
* Provide an easy mapping dispatcher that starts with a common prefix pattern.
*/
public class DefaultEdgeDispatcher extends AbstractEdgeDispatcher {
+
private static final String KEY_ENABLED =
"servicecomb.http.dispatcher.edge.default.enabled";
private static final String KEY_ORDER =
"servicecomb.http.dispatcher.edge.default.order";
@@ -38,6 +48,10 @@ public class DefaultEdgeDispatcher extends
AbstractEdgeDispatcher {
private static final String KEY_PREFIX_SEGMENT_COUNT =
"servicecomb.http.dispatcher.edge.default.prefixSegmentCount";
+ public static final String MICROSERVICE_NAME = "param0";
+
+ public static final String VERSION = "param1";
+
private CompatiblePathVersionMapper versionMapper = new
CompatiblePathVersionMapper();
private String prefix;
@@ -61,27 +75,62 @@ public class DefaultEdgeDispatcher extends
AbstractEdgeDispatcher {
prefix =
DynamicPropertyFactory.getInstance().getStringProperty(KEY_PREFIX, "api").get();
withVersion =
DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_WITH_VERSION,
true).get();
prefixSegmentCount =
DynamicPropertyFactory.getInstance().getIntProperty(KEY_PREFIX_SEGMENT_COUNT,
1).get();
- String regex;
- if (withVersion) {
- regex = "/" + prefix + "/([^\\\\/]+)/([^\\\\/]+)/(.*)";
- } else {
- regex = "/" + prefix + "/([^\\\\/]+)/(.*)";
- }
+ String regex = generateRouteRegex(prefix, withVersion);
+
// cookies handler are enabled by default start from 3.8.3
router.routeWithRegex(regex).handler(createBodyHandler());
router.routeWithRegex(regex).failureHandler(this::onFailure).handler(this::onRequest);
}
+ @VisibleForTesting
+ String generateRouteRegex(String prefix, boolean withVersion) {
+ String version = withVersion ? "/([^\\\\/]+)" : "";
+ return String.format("/%s/([^\\\\/]+)%s/(.*)", prefix, version);
+ }
+
protected void onRequest(RoutingContext context) {
- Map<String, String> pathParams = context.pathParams();
- String microserviceName = pathParams.get("param0");
+ String microserviceName = extractMicroserviceName(context);
+ String versionRule = extractVersionRule(context);
String path = Utils.findActualPath(context.request().path(),
prefixSegmentCount);
- EdgeInvocation edgeInvocation = createEdgeInvocation();
+ if (isFilterChainEnabled()) {
+ requestByFilter(context, microserviceName, versionRule, path);
+ return;
+ }
+
+ requestByHandler(context, microserviceName, versionRule, path);
+ }
+
+ protected boolean isFilterChainEnabled() {
+ return SCBEngine.getInstance().isFilterChainEnabled();
+ }
+
+ @Nullable
+ private String extractMicroserviceName(RoutingContext context) {
+ return context.pathParam(MICROSERVICE_NAME);
+ }
+
+ private String extractVersionRule(RoutingContext context) {
if (withVersion) {
- String pathVersion = pathParams.get("param1");
-
edgeInvocation.setVersionRule(versionMapper.getOrCreate(pathVersion).getVersionRule());
+ String pathVersion = context.pathParam(VERSION);
+ return versionMapper.getOrCreate(pathVersion).getVersionRule();
}
+
+ return DefinitionConst.VERSION_RULE_ALL;
+ }
+
+ protected void requestByFilter(RoutingContext context, String
microserviceName, String versionRule, String path) {
+ HttpServletRequestEx requestEx = new
VertxServerRequestToHttpServletRequest(context);
+ HttpServletResponseEx responseEx = new
VertxServerResponseToHttpServletResponse(context.response());
+ InvocationCreator creator = new EdgeInvocationCreator(context, requestEx,
responseEx,
+ microserviceName, versionRule, path);
+ new RestProducerInvocationFlow(creator, requestEx, responseEx)
+ .run();
+ }
+
+ private void requestByHandler(RoutingContext context, String
microserviceName, String versionRule, String path) {
+ EdgeInvocation edgeInvocation = createEdgeInvocation();
+ edgeInvocation.setVersionRule(versionRule);
edgeInvocation.init(microserviceName, context, path, httpServerFilters);
edgeInvocation.edgeInvoke();
}
diff --git
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderClientFilter.java
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderClientFilter.java
index 9a2632f..95b67dd 100644
---
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderClientFilter.java
+++
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderClientFilter.java
@@ -19,6 +19,7 @@ package org.apache.servicecomb.edge.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.function.BiConsumer;
import org.apache.commons.lang3.StringUtils;
import org.apache.servicecomb.common.rest.filter.HttpClientFilter;
@@ -29,15 +30,17 @@ import org.apache.servicecomb.swagger.invocation.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.netflix.config.ConcurrentCompositeConfiguration;
+import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicPropertyFactory;
public class EdgeAddHeaderClientFilter implements HttpClientFilter {
private static final Logger LOGGER =
LoggerFactory.getLogger(EdgeAddHeaderClientFilter.class);
- private static final String KEY_ENABLED =
"servicecomb.edge.filter.addHeader.enabled";
+ private static final String PREFIX = "servicecomb.edge.filter.addHeader";
- private static final String KEY_HEADERS =
"servicecomb.edge.filter.addHeader.allowedHeaders";
+ private static final String KEY_ENABLED = PREFIX + ".enabled";
+
+ private static final String KEY_HEADERS = PREFIX + ".allowedHeaders";
private List<String> publicHeaders = new ArrayList<>();
@@ -45,13 +48,13 @@ public class EdgeAddHeaderClientFilter implements
HttpClientFilter {
public EdgeAddHeaderClientFilter() {
init();
- ((ConcurrentCompositeConfiguration) DynamicPropertyFactory
- .getBackingConfigurationSource()).addConfigurationListener(event -> {
- if (event.getPropertyName().startsWith(KEY_HEADERS) ||
event.getPropertyName().startsWith(KEY_ENABLED)) {
- LOGGER.info("Public headers config have been changed. Event=" +
event.getType());
- init();
- }
- });
+ ConfigurationManager.getConfigInstance()
+ .addConfigurationListener(event -> {
+ if (StringUtils.startsWith(event.getPropertyName(), PREFIX)) {
+ LOGGER.info("Public headers config have been changed. Event=" +
event.getType());
+ init();
+ }
+ });
}
private void init() {
@@ -75,15 +78,20 @@ public class EdgeAddHeaderClientFilter implements
HttpClientFilter {
@Override
public void beforeSendRequest(Invocation invocation, HttpServletRequestEx
requestEx) {
+ addHeaders(invocation, requestEx::addHeader);
+ }
+
+ public void addHeaders(Invocation invocation, BiConsumer<String, String>
headerAdder) {
if (!invocation.isEdge()) {
return;
}
+
HttpServletRequestEx oldRequest = invocation.getRequestEx();
publicHeaders.forEach(key -> {
- if (StringUtils.isEmpty(oldRequest.getHeader(key))) {
- return;
+ String value = oldRequest.getHeader(key);
+ if (StringUtils.isNotEmpty(value)) {
+ headerAdder.accept(key, value);
}
- requestEx.addHeader(key, oldRequest.getHeader(key));
});
}
diff --git
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java
new file mode 100644
index 0000000..0ea5658
--- /dev/null
+++
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.edge.core;
+
+import java.util.concurrent.CompletableFuture;
+
+import javax.annotation.Nonnull;
+
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.filter.ConsumerFilter;
+import org.apache.servicecomb.core.filter.FilterNode;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.transport.rest.client.RestClientTransportContext;
+import org.springframework.stereotype.Component;
+
+@Component
+public class EdgeAddHeaderFilter implements ConsumerFilter {
+ public static final String NAME = "edge-add-headers";
+
+ private EdgeAddHeaderClientFilter filter = new EdgeAddHeaderClientFilter();
+
+ @Nonnull
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return filter.enabled();
+ }
+
+ @Override
+ public CompletableFuture<Response> onFilter(Invocation invocation,
FilterNode nextNode) {
+ RestClientTransportContext transportContext =
invocation.getTransportContext();
+ return CompletableFuture.completedFuture(null)
+ .thenAccept(v -> filter.addHeaders(invocation,
transportContext.getHttpClientRequest()::putHeader))
+ .thenCompose(v -> nextNode.onFilter(invocation));
+ }
+}
diff --git
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocationCreator.java
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocationCreator.java
new file mode 100644
index 0000000..17d67a6
--- /dev/null
+++
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocationCreator.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.edge.core;
+
+import static
org.apache.servicecomb.edge.core.EdgeInvocation.EDGE_INVOCATION_CONTEXT;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.common.rest.RestVertxProducerInvocationCreator;
+import org.apache.servicecomb.common.rest.locator.OperationLocator;
+import org.apache.servicecomb.common.rest.locator.ServicePathManager;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.invocation.InvocationFactory;
+import
org.apache.servicecomb.core.provider.consumer.MicroserviceReferenceConfig;
+import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
+
+import io.vertx.core.Vertx;
+import io.vertx.ext.web.RoutingContext;
+
+public class EdgeInvocationCreator extends RestVertxProducerInvocationCreator {
+ protected final String microserviceName;
+
+ protected final String versionRule;
+
+ protected final String path;
+
+ protected MicroserviceReferenceConfig microserviceReferenceConfig;
+
+ public EdgeInvocationCreator(RoutingContext routingContext,
+ HttpServletRequestEx requestEx, HttpServletResponseEx responseEx,
+ String microserviceName, String versionRule, String path) {
+ super(routingContext, null, null, requestEx, responseEx);
+
+ this.microserviceName = microserviceName;
+ this.versionRule = versionRule;
+ this.path = path;
+ }
+
+ @Override
+ public CompletableFuture<Invocation> createAsync() {
+ return createMicroserviceReferenceConfig()
+ .thenCompose(v -> super.createAsync());
+ }
+
+ protected CompletableFuture<Void> createMicroserviceReferenceConfig() {
+ return SCBEngine.getInstance()
+ .createMicroserviceReferenceConfigAsync(microserviceName, versionRule)
+ .thenAccept(mrc -> {
+ this.microserviceReferenceConfig = mrc;
+ this.microserviceMeta = mrc.getLatestMicroserviceMeta();
+ });
+ }
+
+ @Override
+ protected OperationLocator locateOperation(ServicePathManager
servicePathManager) {
+ return servicePathManager.consumerLocateOperation(path,
requestEx.getMethod());
+ }
+
+ @Override
+ protected void initInvocationContext(Invocation invocation) {
+ // do not read InvocationContext from HTTP header, for security reason
+ }
+
+ @Override
+ protected Invocation createInstance() {
+ ReferenceConfig referenceConfig = microserviceReferenceConfig
+ .createReferenceConfig(restOperationMeta.getOperationMeta());
+
+ Invocation invocation = InvocationFactory.forConsumer(referenceConfig,
+ restOperationMeta.getOperationMeta(),
+ restOperationMeta.getOperationMeta().buildBaseConsumerRuntimeType(),
+ null);
+ invocation.setSync(false);
+ invocation.setEdge(true);
+ invocation.addLocalContext(EDGE_INVOCATION_CONTEXT,
Vertx.currentContext());
+
+ return invocation;
+ }
+}
diff --git
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeRestTransportClient.java
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeRestTransportClient.java
index dcd3b97..f8229e0 100644
---
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeRestTransportClient.java
+++
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeRestTransportClient.java
@@ -32,14 +32,9 @@ public class EdgeRestTransportClient extends
RestTransportClient {
Context invocationContext = (Context)
invocation.getHandlerContext().get(EdgeInvocation.EDGE_INVOCATION_CONTEXT);
URIEndpointObject endpoint = (URIEndpointObject)
invocation.getEndpoint().getAddress();
- HttpClientWithContext httpClientWithContext;
- if (endpoint.isHttp2Enabled()) {
- httpClientWithContext = HttpClients
- .getClient(Http2TransportHttpClientOptionsSPI.CLIENT_NAME,
invocation.isSync(), invocationContext);
- } else {
- httpClientWithContext = HttpClients
- .getClient(HttpTransportHttpClientOptionsSPI.CLIENT_NAME,
invocation.isSync(), invocationContext);
- }
- return httpClientWithContext;
+ String clientName = endpoint.isHttp2Enabled() ?
+ Http2TransportHttpClientOptionsSPI.CLIENT_NAME :
+ HttpTransportHttpClientOptionsSPI.CLIENT_NAME;
+ return HttpClients.getClient(clientName, invocation.isSync(),
invocationContext);
}
}
diff --git
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java
new file mode 100644
index 0000000..71968af
--- /dev/null
+++
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.edge.core;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import javax.annotation.Nonnull;
+
+import org.apache.servicecomb.common.rest.filter.inner.RestServerCodecFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.filter.FilterNode;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.swagger.invocation.context.TransportContext;
+import org.springframework.stereotype.Component;
+
+@Component
+public class EdgeServerCodecFilter extends RestServerCodecFilter {
+ public static final String NAME = "edge-server-codec";
+
+ @Nonnull
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Nonnull
+ @Override
+ public List<InvocationType> getInvocationTypes() {
+ return Collections.singletonList(InvocationType.CONSUMER);
+ }
+
+ @Override
+ public CompletableFuture<Response> onFilter(Invocation invocation,
FilterNode nextNode) {
+ if (invocation.getRequestEx() == null) {
+ // to support normal consumer invocation in edge process
+ return nextNode.onFilter(invocation);
+ }
+
+ return super.onFilter(invocation, nextNode);
+ }
+
+ // save and restore transportContext to support edge invocation
+ @Override
+ protected CompletableFuture<Response> invokeNext(Invocation invocation,
FilterNode nextNode) {
+ TransportContext transportContext = invocation.getTransportContext();
+ return nextNode.onFilter(invocation)
+ .whenComplete((r, e) ->
invocation.setTransportContext(transportContext));
+ }
+}
diff --git
a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestDefaultEdgeDispatcher.java
b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestDefaultEdgeDispatcher.java
index e74f13a..639eb02 100644
---
a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestDefaultEdgeDispatcher.java
+++
b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestDefaultEdgeDispatcher.java
@@ -17,9 +17,10 @@
package org.apache.servicecomb.edge.core;
-import java.util.HashMap;
-import java.util.Map;
+import static
org.apache.servicecomb.edge.core.DefaultEdgeDispatcher.MICROSERVICE_NAME;
+import static org.apache.servicecomb.edge.core.DefaultEdgeDispatcher.VERSION;
+import org.apache.servicecomb.core.SCBEngine;
import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
import org.junit.After;
import org.junit.Assert;
@@ -52,21 +53,25 @@ public class TestDefaultEdgeDispatcher {
, @Mocked RoutingContext context
, @Mocked HttpServerRequest requst
, @Mocked EdgeInvocation invocation) {
- DefaultEdgeDispatcher dispatcher = new DefaultEdgeDispatcher();
- Map<String, String> pathParams = new HashMap<>();
- pathParams.put("param0", "testService");
- pathParams.put("param1", "v1");
+ DefaultEdgeDispatcher dispatcher = new DefaultEdgeDispatcher() {
+ @Override
+ protected boolean isFilterChainEnabled() {
+ return false;
+ }
+ };
- new Expectations() {
+ new Expectations(SCBEngine.class) {
{
- router.routeWithRegex("/api/([^\\\\/]+)/([^\\\\/]+)/(.*)");
+ router.routeWithRegex(dispatcher.generateRouteRegex("api", true));
result = route;
route.handler((Handler<RoutingContext>) any);
result = route;
route.failureHandler((Handler<RoutingContext>) any);
result = route;
- context.pathParams();
- result = pathParams;
+ context.pathParam(MICROSERVICE_NAME);
+ result = "testService";
+ context.pathParam(VERSION);
+ result = "v1";
context.request();
result = requst;
requst.path();
diff --git a/integration-tests/it-edge/src/main/resources/microservice.yaml
b/integration-tests/it-edge/src/main/resources/microservice.yaml
index 81fad60..a0f10ae 100644
--- a/integration-tests/it-edge/src/main/resources/microservice.yaml
+++ b/integration-tests/it-edge/src/main/resources/microservice.yaml
@@ -19,6 +19,12 @@ service_description:
name: it-edge
servicecomb:
+ filter-chains:
+ transport:
+ scb-consumer-transport:
+ rest: rest-client-codec, edge-add-headers, rest-client-sender
+ definition:
+ scb-consumer: edge-server-codec, simple-load-balance,
scb-consumer-transport
handler:
chain:
Consumer:
diff --git
a/service-registry/registry-lightweight/src/main/java/org/apache/servicecomb/registry/lightweight/Self.java
b/service-registry/registry-lightweight/src/main/java/org/apache/servicecomb/registry/lightweight/Self.java
index 7f42141..395bdcc 100644
---
a/service-registry/registry-lightweight/src/main/java/org/apache/servicecomb/registry/lightweight/Self.java
+++
b/service-registry/registry-lightweight/src/main/java/org/apache/servicecomb/registry/lightweight/Self.java
@@ -51,15 +51,15 @@ public class Self implements InitializingBean {
public Self init(AbstractConfiguration configuration) {
MicroserviceFactory factory = new MicroserviceFactory();
microservice = factory.create(configuration);
- microservice.setServiceId(String.format("%s/%s/%s/%s",
+ microservice.serviceId(String.format("%s/%s/%s/%s",
microservice.getEnvironment(),
microservice.getAppId(),
microservice.getServiceName(),
microservice.getVersion()));
- instance = microservice.getInstance();
- instance.setInstanceId(UUID.randomUUID().toString());
- instance.setServiceId(microservice.getServiceId());
+ instance = microservice.getInstance()
+ .instanceId(UUID.randomUUID().toString())
+ .serviceId(microservice.getServiceId());
microserviceInfo
.setMicroservice(microservice)
diff --git
a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerConnection.java
b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerConnection.java
index 716efd3..bb50fbc 100644
---
a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerConnection.java
+++
b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerConnection.java
@@ -16,6 +16,8 @@
*/
package org.apache.servicecomb.transport.highway;
+import java.util.concurrent.CompletableFuture;
+
import javax.ws.rs.core.Response.Status;
import org.apache.servicecomb.codec.protobuf.definition.ProtobufManager;
@@ -136,7 +138,7 @@ public class HighwayServerConnection extends
TcpServerConnection implements TcpB
}
}
- public Invocation createInvocation(long msgId, RequestHeader header, Buffer
bodyBuffer) {
+ public CompletableFuture<Invocation> createInvocation(long msgId,
RequestHeader header, Buffer bodyBuffer) {
MicroserviceMeta microserviceMeta =
SCBEngine.getInstance().getProducerMicroserviceMeta();
SchemaMeta schemaMeta =
microserviceMeta.ensureFindSchemaMeta(header.getSchemaId());
OperationMeta operationMeta =
schemaMeta.ensureFindOperation(header.getOperationName());
@@ -154,6 +156,6 @@ public class HighwayServerConnection extends
TcpServerConnection implements TcpB
.setOperationProtobuf(ProtobufManager.getOrCreateOperation(invocation));
invocation.setTransportContext(transportContext);
- return invocation;
+ return CompletableFuture.completedFuture(invocation);
}
}
diff --git
a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java
b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java
index 0a8e581..9c1885c 100644
---
a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java
+++
b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java
@@ -32,9 +32,9 @@ import org.apache.servicecomb.core.event.ServerAccessLogEvent;
import org.apache.servicecomb.core.transport.AbstractTransport;
import org.apache.servicecomb.foundation.common.event.EventManager;
import org.apache.servicecomb.foundation.common.net.URIEndpointObject;
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
import org.apache.servicecomb.foundation.common.utils.ExceptionUtils;
import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-
import org.apache.servicecomb.foundation.ssl.SSLCustom;
import org.apache.servicecomb.foundation.ssl.SSLOption;
import org.apache.servicecomb.foundation.ssl.SSLOptionFactory;
@@ -219,7 +219,9 @@ public class RestServerVerticle extends AbstractVerticle {
}
private void initDispatcher(Router mainRouter) {
- List<VertxHttpDispatcher> dispatchers =
SPIServiceUtils.getSortedService(VertxHttpDispatcher.class);
+ List<VertxHttpDispatcher> dispatchers =
SPIServiceUtils.loadSortedService(VertxHttpDispatcher.class);
+ BeanUtils.addBeans(VertxHttpDispatcher.class, dispatchers);
+
for (VertxHttpDispatcher dispatcher : dispatchers) {
if (dispatcher.enabled()) {
dispatcher.init(mainRouter);
diff --git
a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxHttpDispatcher.java
b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxHttpDispatcher.java
index cc8b6dc..cb96d8c 100644
---
a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxHttpDispatcher.java
+++
b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxHttpDispatcher.java
@@ -17,11 +17,13 @@
package org.apache.servicecomb.transport.rest.vertx;
-import io.vertx.ext.web.Router;
+import org.apache.servicecomb.foundation.common.utils.SPIEnabled;
+import org.apache.servicecomb.foundation.common.utils.SPIOrder;
-public interface VertxHttpDispatcher {
- int getOrder();
+import io.vertx.ext.web.Router;
+public interface VertxHttpDispatcher extends SPIOrder, SPIEnabled {
+ @Override
default boolean enabled() {
return true;
}