[SCB-2671]support beforeSendRequestAsync so that HttpClient filter ca… (#3291)
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilter.java
index a139712..9fe6d1b 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilter.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilter.java
@@ -17,6 +17,8 @@
package org.apache.servicecomb.common.rest.filter;
+import java.util.concurrent.CompletableFuture;
+
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
@@ -29,7 +31,30 @@
int getOrder();
- void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx);
+ /**
+ * callback method before send a client request.
+ *
+ * @Deprecated this method may be called in an event-loop thread, do not add blocking
+ * methods. Implement #beforeSendRequestAsync instead.
+ */
+ @Deprecated
+ default void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+
+ }
+
+ /**
+ * callback method before send a client request.
+ */
+ default CompletableFuture<Void> beforeSendRequestAsync(Invocation invocation, HttpServletRequestEx requestEx) {
+ CompletableFuture<Void> future = new CompletableFuture<>();
+ try {
+ beforeSendRequest(invocation, requestEx);
+ future.complete(null);
+ } catch (Throwable e) {
+ future.completeExceptionally(e);
+ }
+ return future;
+ }
// if finished, then return a none null response
// if return a null response, then sdk will call next filter.afterReceive
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilterBeforeSendRequestExecutor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilterBeforeSendRequestExecutor.java
new file mode 100644
index 0000000..eab6217
--- /dev/null
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilterBeforeSendRequestExecutor.java
@@ -0,0 +1,92 @@
+/*
+ * 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.common.rest.filter;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+
+public class HttpClientFilterBeforeSendRequestExecutor {
+ private final List<HttpClientFilter> httpClientFilters;
+
+ private final Invocation invocation;
+
+ private final HttpServletRequestEx requestEx;
+
+ private int currentIndex;
+
+ private final CompletableFuture<Void> future = new CompletableFuture<>();
+
+ public HttpClientFilterBeforeSendRequestExecutor(List<HttpClientFilter> httpClientFilters, Invocation invocation,
+ HttpServletRequestEx requestEx) {
+ this.httpClientFilters = httpClientFilters;
+ this.invocation = invocation;
+ this.requestEx = requestEx;
+ }
+
+ public CompletableFuture<Void> run() {
+ doRun();
+
+ return future;
+ }
+
+ protected CompletableFuture<Void> safeInvoke(HttpClientFilter httpClientFilter) {
+ try {
+ if (httpClientFilter.enabled()) {
+ CompletableFuture<Void> future = httpClientFilter.beforeSendRequestAsync(invocation, requestEx);
+ if (future == null) {
+ future = new CompletableFuture<>();
+ future.completeExceptionally(new IllegalStateException(
+ "HttpClientFilter beforeSendRequestAsync can not return null, do not override it. Class="
+ + httpClientFilter.getClass()
+ .getName()));
+ }
+ return future;
+ } else {
+ CompletableFuture<Void> eFuture = new CompletableFuture<>();
+ eFuture.complete(null);
+ return eFuture;
+ }
+ } catch (Throwable e) {
+ CompletableFuture<Void> eFuture = new CompletableFuture<>();
+ eFuture.completeExceptionally(e);
+ return eFuture;
+ }
+ }
+
+ protected void doRun() {
+ if (currentIndex == httpClientFilters.size()) {
+ future.complete(null);
+ return;
+ }
+
+ HttpClientFilter httpServerFilter = httpClientFilters.get(currentIndex);
+ currentIndex++;
+
+ CompletableFuture<Void> stepFuture = safeInvoke(httpServerFilter);
+ stepFuture.whenComplete((v, e) -> {
+ if (e == null) {
+ doRun();
+ return;
+ }
+
+ future.completeExceptionally(e);
+ });
+ }
+}
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilter.java
index b809660..639bd55 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilter.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilter.java
@@ -43,7 +43,7 @@
Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx);
/**
- * @param invocation maybe null
+ * callback method before send a server response.
*/
default CompletableFuture<Void> beforeSendResponseAsync(Invocation invocation, HttpServletResponseEx responseEx) {
CompletableFuture<Void> future = new CompletableFuture<>();
@@ -57,8 +57,12 @@
}
/**
- * @param invocation maybe null
+ * callback method before send a server response.
+ *
+ * @Deprecated this method may be called in an event-loop thread, do not add blocking
+ * methods. Implement #beforeSendResponseAsync instead.
*/
+ @Deprecated
default void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) {
}
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ClientRestArgsFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ClientRestArgsFilter.java
index 8babd97..a532833 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ClientRestArgsFilter.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ClientRestArgsFilter.java
@@ -17,6 +17,8 @@
package org.apache.servicecomb.common.rest.filter.inner;
+import java.util.concurrent.CompletableFuture;
+
import org.apache.servicecomb.common.rest.RestConst;
import org.apache.servicecomb.common.rest.codec.RestCodec;
import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl;
@@ -27,7 +29,6 @@
import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
import org.apache.servicecomb.swagger.invocation.Response;
-import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory;
public class ClientRestArgsFilter implements HttpClientFilter {
@@ -37,8 +38,8 @@
}
@Override
- @SuppressWarnings("unchecked")
- public void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+ public CompletableFuture<Void> beforeSendRequestAsync(Invocation invocation, HttpServletRequestEx requestEx) {
+ CompletableFuture<Void> result = new CompletableFuture<>();
RestClientRequestImpl restClientRequest = (RestClientRequestImpl) invocation.getHandlerContext()
.get(RestConst.INVOCATION_HANDLER_REQUESTCLIENT);
OperationMeta operationMeta = invocation.getOperationMeta();
@@ -47,9 +48,11 @@
RestCodec.argsToRest(invocation.getSwaggerArguments(), swaggerRestOperation,
restClientRequest);
requestEx.setBodyBuffer(restClientRequest.getBodyBuffer());
+ result.complete(null);
} catch (Throwable e) {
- throw ExceptionFactory.convertConsumerException(e);
+ result.completeExceptionally(e);
}
+ return result;
}
@Override
diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestAbstractRestInvocation.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestAbstractRestInvocation.java
index 0b7734d..75728a3 100644
--- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestAbstractRestInvocation.java
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestAbstractRestInvocation.java
@@ -85,6 +85,7 @@
import org.mockito.MockedStatic;
import org.mockito.Mockito;
+@SuppressWarnings("deprecation")
public class TestAbstractRestInvocation {
HttpServletRequestEx requestEx = Mockito.mock(HttpServletRequestEx.class);
diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/HttpClientFilterBaseForTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/HttpClientFilterBaseForTest.java
new file mode 100644
index 0000000..7903b19
--- /dev/null
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/HttpClientFilterBaseForTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.common.rest.filter;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
+import org.apache.servicecomb.swagger.invocation.Response;
+
+public class HttpClientFilterBaseForTest implements HttpClientFilter {
+ @Override
+ public int getOrder() {
+ return 0;
+ }
+
+ @Override
+ public CompletableFuture<Void> beforeSendRequestAsync(Invocation invocation, HttpServletRequestEx requestEx) {
+ return null;
+ }
+
+ @Override
+ public Response afterReceiveResponse(Invocation invocation, HttpServletResponseEx responseEx) {
+ return null;
+ }
+}
diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpClientFilter.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpClientFilter.java
new file mode 100644
index 0000000..afc788b
--- /dev/null
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpClientFilter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.common.rest.filter;
+
+import java.util.Arrays;
+import java.util.concurrent.ExecutionException;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestHttpClientFilter {
+ @Test
+ public void asyncFailed() {
+ HttpClientFilter filter = new HttpClientFilterBaseForTest();
+ HttpClientFilterBeforeSendRequestExecutor executor =
+ new HttpClientFilterBeforeSendRequestExecutor(Arrays.asList(filter), null, null);
+ Assertions.assertThrows(ExecutionException.class, () -> executor.run().get());
+ }
+}
diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilter.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilter.java
index 584a35a..37449a3 100644
--- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilter.java
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilter.java
@@ -39,6 +39,7 @@
public void asyncFailed() throws InterruptedException, ExecutionException {
HttpServerFilter filter = new HttpServerFilterBaseForTest() {
@Override
+ @SuppressWarnings("deprecation")
public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) {
throw new RuntimeExceptionWithoutStackTrace();
}
diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java
index 10c443b..ea2a539 100644
--- a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java
+++ b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java
@@ -493,7 +493,7 @@
long start = System.currentTimeMillis();
while (true) {
long remaining = invocationStartedCounter.get() - invocationFinishedCounter.get();
- if (remaining == 0) {
+ if (remaining <= 0) {
return;
}
diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureResponseFilter.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureResponseFilter.java
index 4d9a380..87d3e21 100644
--- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureResponseFilter.java
+++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureResponseFilter.java
@@ -17,6 +17,7 @@
package org.apache.servicecomb.demo.edge.service.encrypt.filter;
import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletableFuture;
import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
import org.apache.servicecomb.core.Invocation;
@@ -48,14 +49,14 @@
}
@Override
- public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) {
+ public CompletableFuture<Void> beforeSendResponseAsync(Invocation invocation, HttpServletResponseEx responseEx) {
if (invocation == null) {
- return;
+ return CompletableFuture.completedFuture(null);
}
EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
if (encryptContext == null) {
- return;
+ return CompletableFuture.completedFuture(null);
}
Hcr hcr = encryptContext.getHcr();
@@ -72,5 +73,7 @@
body = body.substring(0, body.length() - 1) + ",\"signature\":\"" + signature + "\"}";
responseEx.setBodyBuffer(Buffer.buffer(body));
}
+
+ return CompletableFuture.completedFuture(null);
}
}
diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsDemoHttpServerFilter.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsDemoHttpServerFilter.java
index 0258474..e89d3da 100644
--- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsDemoHttpServerFilter.java
+++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsDemoHttpServerFilter.java
@@ -39,6 +39,7 @@
}
@Override
+ @SuppressWarnings("deprecation")
public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) {
// in 404 situation, invocation is null and a NPE is thrown
LOGGER.info("JaxrsDemoHttpServerFilter is called, operation=[{}]", invocation.getOperationName());
diff --git a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ClientSignature.java b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ClientSignature.java
index aa715d2..84bbe67 100644
--- a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ClientSignature.java
+++ b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ClientSignature.java
@@ -17,6 +17,8 @@
package org.apache.servicecomb.demo.signature;
+import java.util.concurrent.CompletableFuture;
+
import javax.ws.rs.core.Response.Status;
import org.apache.servicecomb.common.rest.filter.HttpClientFilter;
@@ -36,9 +38,10 @@
}
@Override
- public void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+ public CompletableFuture<Void> beforeSendRequestAsync(Invocation invocation, HttpServletRequestEx requestEx) {
String signature = SignatureUtils.genSignature(requestEx);
requestEx.setHeader("signature", signature);
+ return CompletableFuture.completedFuture(null);
}
@Override
diff --git a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java
index 8f6e181..1b623c3 100644
--- a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java
+++ b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java
@@ -57,6 +57,7 @@
}
@Override
+ @SuppressWarnings("deprecation")
public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) {
String signature = SignatureUtils.genSignature(responseEx);
responseEx.addHeader("signature", signature);
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 c315393..49258fa 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 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import org.apache.commons.lang3.StringUtils;
@@ -77,8 +78,9 @@
}
@Override
- public void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+ public CompletableFuture<Void> beforeSendRequestAsync(Invocation invocation, HttpServletRequestEx requestEx) {
addHeaders(invocation, requestEx::addHeader);
+ return CompletableFuture.completedFuture(null);
}
public void addHeaders(Invocation invocation, BiConsumer<String, String> headerAdder) {
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java
index b625135..281b112 100644
--- a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java
@@ -17,6 +17,7 @@
package org.apache.servicecomb.it.edge.encrypt.filter;
import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletableFuture;
import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
import org.apache.servicecomb.core.Invocation;
@@ -48,14 +49,14 @@
}
@Override
- public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) {
+ public CompletableFuture<Void> beforeSendResponseAsync(Invocation invocation, HttpServletResponseEx responseEx) {
if (invocation == null) {
- return;
+ return CompletableFuture.completedFuture(null);
}
EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
if (encryptContext == null) {
- return;
+ return CompletableFuture.completedFuture(null);
}
Hcr hcr = encryptContext.getHcr();
@@ -72,5 +73,6 @@
body = body.substring(0, body.length() - 1) + ",\"signature\":\"" + signature + "\"}";
responseEx.setBodyBuffer(Buffer.buffer(body));
}
+ return CompletableFuture.completedFuture(null);
}
}
diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/RestTemplateCopyHeaderFilter.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/RestTemplateCopyHeaderFilter.java
index c37a3c3..e8b674d 100644
--- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/RestTemplateCopyHeaderFilter.java
+++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/RestTemplateCopyHeaderFilter.java
@@ -17,6 +17,8 @@
package org.apache.servicecomb.provider.springmvc.reference;
+import java.util.concurrent.CompletableFuture;
+
import org.apache.servicecomb.common.rest.RestConst;
import org.apache.servicecomb.common.rest.filter.HttpClientFilter;
import org.apache.servicecomb.core.Invocation;
@@ -36,10 +38,10 @@
}
@Override
- public void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+ public CompletableFuture<Void> beforeSendRequestAsync(Invocation invocation, HttpServletRequestEx requestEx) {
HttpHeaders httpHeaders = (HttpHeaders) invocation.getHandlerContext().get(RestConst.CONSUMER_HEADER);
if (httpHeaders == null) {
- return;
+ return CompletableFuture.completedFuture(null);
}
httpHeaders.forEach((key, values) -> {
@@ -57,6 +59,7 @@
requestEx.addHeader(key, value);
}
});
+ return CompletableFuture.completedFuture(null);
}
@Override
diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestRestTemplateCopyHeaderFilter.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestRestTemplateCopyHeaderFilter.java
index e94bb9f..7e02c75 100644
--- a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestRestTemplateCopyHeaderFilter.java
+++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestRestTemplateCopyHeaderFilter.java
@@ -20,6 +20,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ExecutionException;
import org.apache.servicecomb.common.rest.RestConst;
import org.apache.servicecomb.core.Invocation;
@@ -42,7 +43,7 @@
}
@Test
- public void beforeSendRequestNoHeader(@Mocked Invocation invocation) {
+ public void beforeSendRequestNoHeader(@Mocked Invocation invocation) throws ExecutionException, InterruptedException {
Map<String, Object> context = new HashMap<>();
new Expectations() {
{
@@ -52,12 +53,13 @@
};
HttpServletRequestEx requestEx = new CommonToHttpServletRequest(null, null, new HttpHeaders(), null, false);
- filter.beforeSendRequest(invocation, requestEx);
+ filter.beforeSendRequestAsync(invocation, requestEx).get();
Assertions.assertFalse(requestEx.getHeaderNames().hasMoreElements());
}
@Test
- public void beforeSendRequestWithNullHeader(@Mocked Invocation invocation) {
+ public void beforeSendRequestWithNullHeader(@Mocked Invocation invocation)
+ throws ExecutionException, InterruptedException {
Map<String, Object> context = new HashMap<>(1);
HttpHeaders httpHeaders = new HttpHeaders();
context.put(RestConst.CONSUMER_HEADER, httpHeaders);
@@ -72,14 +74,15 @@
};
HttpServletRequestEx requestEx = new CommonToHttpServletRequest(null, null, new HttpHeaders(), null, false);
- filter.beforeSendRequest(invocation, requestEx);
+ filter.beforeSendRequestAsync(invocation, requestEx).get();
Assertions.assertEquals("headerValue0", requestEx.getHeader("headerName0"));
Assertions.assertEquals("headerValue2", requestEx.getHeader("headerName2"));
Assertions.assertNull(requestEx.getHeader("headerName1"));
}
@Test
- public void beforeSendRequestHaveHeader(@Mocked Invocation invocation) {
+ public void beforeSendRequestHaveHeader(@Mocked Invocation invocation)
+ throws ExecutionException, InterruptedException {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("name", "value");
@@ -93,12 +96,13 @@
};
HttpServletRequestEx requestEx = new CommonToHttpServletRequest(null, null, new HttpHeaders(), null, false);
- filter.beforeSendRequest(invocation, requestEx);
+ filter.beforeSendRequestAsync(invocation, requestEx).get();
MatcherAssert.assertThat(Collections.list(requestEx.getHeaders("name")), Matchers.contains("value"));
}
@Test
- public void beforeSendRequestSkipContentLength(@Mocked Invocation invocation) {
+ public void beforeSendRequestSkipContentLength(@Mocked Invocation invocation)
+ throws ExecutionException, InterruptedException {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_LENGTH, "0");
@@ -112,7 +116,7 @@
};
HttpServletRequestEx requestEx = new CommonToHttpServletRequest(null, null, new HttpHeaders(), null, false);
- filter.beforeSendRequest(invocation, requestEx);
+ filter.beforeSendRequestAsync(invocation, requestEx).get();
Assertions.assertNull((requestEx.getHeader(HttpHeaders.CONTENT_LENGTH)));
}
diff --git a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/DefaultHttpClientFilter.java b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/DefaultHttpClientFilter.java
index d41b156..30cc9b7 100644
--- a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/DefaultHttpClientFilter.java
+++ b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/DefaultHttpClientFilter.java
@@ -28,7 +28,6 @@
import org.apache.servicecomb.common.rest.filter.HttpClientFilter;
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.core.definition.OperationMeta;
-import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
import org.apache.servicecomb.swagger.invocation.Response;
import org.apache.servicecomb.swagger.invocation.context.HttpStatus;
@@ -56,11 +55,6 @@
return enabled;
}
- @Override
- public void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) {
-
- }
-
protected ProduceProcessor findProduceProcessor(RestOperationMeta restOperation,
HttpServletResponseEx responseEx) {
String contentType = responseEx.getHeader(HttpHeaders.CONTENT_TYPE);
diff --git a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java
index 18339c1..6ddf1e2 100644
--- a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java
+++ b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java
@@ -18,6 +18,7 @@
package org.apache.servicecomb.transport.rest.client.http;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeoutException;
import javax.ws.rs.core.Response.Status;
@@ -27,6 +28,7 @@
import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl;
import org.apache.servicecomb.common.rest.definition.RestOperationMeta;
import org.apache.servicecomb.common.rest.filter.HttpClientFilter;
+import org.apache.servicecomb.common.rest.filter.HttpClientFilterBeforeSendRequestExecutor;
import org.apache.servicecomb.core.Const;
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.core.definition.OperationConfig;
@@ -121,28 +123,25 @@
}
HttpServletRequestEx requestEx = new VertxClientRequestToHttpServletRequest(clientRequest, requestBodyBuffer);
invocation.getInvocationStageTrace().startClientFiltersRequest();
- for (HttpClientFilter filter : httpClientFilters) {
- if (filter.enabled()) {
- filter.beforeSendRequest(invocation, requestEx);
- }
- }
- // 从业务线程转移到网络线程中去发送
- invocation.onStartSendRequest();
- httpClientWithContext.runOnContext(httpClient -> {
- clientRequest.setTimeout(operationMeta.getConfig().getMsRequestTimeout());
- clientRequest.response().onComplete(asyncResult -> {
- if (asyncResult.failed()) {
- fail(asyncResult.cause());
- return;
- }
- handleResponse(asyncResult.result());
+ return Future.fromCompletionStage(executeHttpClientFilters(requestEx).thenCompose((v) -> {
+ // 从业务线程转移到网络线程中去发送
+ invocation.onStartSendRequest();
+ httpClientWithContext.runOnContext(httpClient -> {
+ clientRequest.setTimeout(operationMeta.getConfig().getMsRequestTimeout());
+ clientRequest.response().onComplete(asyncResult -> {
+ if (asyncResult.failed()) {
+ fail(asyncResult.cause());
+ return;
+ }
+ handleResponse(asyncResult.result());
+ });
+ processServiceCombHeaders(invocation, operationMeta);
+ restClientRequest.end()
+ .onComplete((t) -> invocation.getInvocationStageTrace().finishWriteToBuffer(System.nanoTime()));
});
- processServiceCombHeaders(invocation, operationMeta);
- restClientRequest.end()
- .onComplete((t) -> invocation.getInvocationStageTrace().finishWriteToBuffer(System.nanoTime()));
- });
- return Future.succeededFuture();
+ return CompletableFuture.completedFuture((Void) null);
+ }));
}).onFailure(failure -> {
invocation.getTraceIdLogger()
.error(LOGGER, "Failed to send request, alreadyFailed:{}, local:{}, remote:{}, message={}.",
@@ -152,6 +151,13 @@
});
}
+ private CompletableFuture<Void> executeHttpClientFilters(HttpServletRequestEx requestEx) {
+ HttpClientFilterBeforeSendRequestExecutor exec =
+ new HttpClientFilterBeforeSendRequestExecutor(httpClientFilters, invocation, requestEx);
+ return exec.run();
+ }
+
+
/**
* If this is a 3rd party invocation, ServiceComb related headers should be removed by default to hide inner
* implementation. Otherwise, the InvocationContext will be set into the request headers.