This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 72f4538b96 fix: handle null or blank rpcExt(#6650) (#7146)
72f4538b96 is described below
commit 72f4538b962cfb22527be1d060925178301e4fdc
Author: Southern <[email protected]>
AuthorDate: Mon Sep 21 16:13:50 2026 +0800
fix: handle null or blank rpcExt(#6650) (#7146)
* fix(grpc): handle null or blank rpcExt
Fall back to default gRPC extension settings when rpcExt deserialization
returns null. Use a 5000ms timeout and UNARY
method type, and add regression coverage for null, blank, and explicitly
configured rpcExt values.
* fix(grpc): handle blank rpcExt before deserialization
Handle null, empty, and whitespace-only rpcExt values before Gson
deserialization to avoid version-dependent parsing
behavior. Fall back to default gRPC settings and add regression tests for
each boundary case.
---------
Co-authored-by: aias00 <[email protected]>
Co-authored-by: zhengpeng <[email protected]>
---
.../org/apache/shenyu/plugin/grpc/GrpcPlugin.java | 7 ++--
.../apache/shenyu/plugin/grpc/GrpcPluginTest.java | 40 +++++++++++++++++++---
2 files changed, 40 insertions(+), 7 deletions(-)
diff --git
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/GrpcPlugin.java
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/GrpcPlugin.java
index 4be1aa32c4..2ff62f367a 100644
---
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/GrpcPlugin.java
+++
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/GrpcPlugin.java
@@ -104,7 +104,10 @@ public class GrpcPlugin extends AbstractShenyuPlugin {
.map(InetAddress::getHostAddress)
.orElse(StringUtils.EMPTY)).attach();
- GrpcExtInfo extInfo =
GsonUtils.getGson().fromJson(metaData.getRpcExt(), GrpcExtInfo.class);
+ GrpcExtInfo extInfo = StringUtils.isBlank(metaData.getRpcExt())
+ ? new GrpcExtInfo()
+ :
Optional.ofNullable(GsonUtils.getGson().fromJson(metaData.getRpcExt(),
GrpcExtInfo.class))
+ .orElseGet(GrpcExtInfo::new);
CallOptions callOptions =
CallOptions.DEFAULT.withDeadlineAfter(extInfo.timeout, TimeUnit.MILLISECONDS);
Map<String, Map<String, String>> rpcContext =
exchange.getAttribute(Constants.GENERAL_CONTEXT);
Optional.ofNullable(rpcContext).map(context ->
context.get(PluginEnum.GRPC.getName())).ifPresent(
@@ -168,7 +171,7 @@ public class GrpcPlugin extends AbstractShenyuPlugin {
private Integer timeout = 5000;
- private MethodDescriptor.MethodType methodType;
+ private MethodDescriptor.MethodType methodType =
MethodDescriptor.MethodType.UNARY;
public Integer getTimeout() {
return timeout;
diff --git
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/GrpcPluginTest.java
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/GrpcPluginTest.java
index 72170900df..6ce28918b1 100644
---
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/GrpcPluginTest.java
+++
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/GrpcPluginTest.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.plugin.grpc;
+import io.grpc.MethodDescriptor;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.dto.MetaData;
import org.apache.shenyu.common.dto.RuleData;
@@ -94,21 +95,49 @@ public class GrpcPluginTest {
@Test
public void testDoExecute() throws ClassNotFoundException,
NoSuchFieldException, IllegalAccessException {
ServerWebExchange exchange = getServerWebExchange(new
InetSocketAddress("127.0.0.1", 8090));
- executeRequest(exchange, "127.0.0.1");
+ executeRequest(exchange, "127.0.0.1", getMetaData(),
MethodDescriptor.MethodType.SERVER_STREAMING);
}
@Test
public void testDoExecuteWithNullRemoteAddress()
throws ClassNotFoundException, NoSuchFieldException,
IllegalAccessException {
ServerWebExchange exchange = getServerWebExchange();
- executeRequest(exchange, "");
+ executeRequest(exchange, "", getMetaData(),
MethodDescriptor.MethodType.SERVER_STREAMING);
+ }
+
+ @Test
+ public void testDoExecuteWithNullRpcExt()
+ throws ClassNotFoundException, NoSuchFieldException,
IllegalAccessException {
+ ServerWebExchange exchange = getServerWebExchange();
+ MetaData metaData = getMetaData();
+ metaData.setRpcExt(null);
+ executeRequest(exchange, "", metaData,
MethodDescriptor.MethodType.UNARY);
+ }
+
+ @Test
+ public void testDoExecuteWithEmptyRpcExt()
+ throws ClassNotFoundException, NoSuchFieldException,
IllegalAccessException {
+ ServerWebExchange exchange = getServerWebExchange();
+ MetaData metaData = getMetaData();
+ metaData.setRpcExt("");
+ executeRequest(exchange, "", metaData,
MethodDescriptor.MethodType.UNARY);
+ }
+
+ @Test
+ public void testDoExecuteWithBlankRpcExt()
+ throws ClassNotFoundException, NoSuchFieldException,
IllegalAccessException {
+ ServerWebExchange exchange = getServerWebExchange();
+ MetaData metaData = getMetaData();
+ metaData.setRpcExt(" ");
+ executeRequest(exchange, "", metaData,
MethodDescriptor.MethodType.UNARY);
}
@SuppressWarnings("unchecked")
- private void executeRequest(final ServerWebExchange exchange, final String
expectedRemoteAddress)
+ private void executeRequest(final ServerWebExchange exchange, final String
expectedRemoteAddress,
+ final MetaData metaData, final
MethodDescriptor.MethodType expectedMethodType)
throws ClassNotFoundException, NoSuchFieldException,
IllegalAccessException {
exchange.getAttributes().put(Constants.PARAM_TRANSFORM, "{message:1}");
- exchange.getAttributes().put(Constants.META_DATA, getMetaData());
+ exchange.getAttributes().put(Constants.META_DATA, metaData);
Class<?> grpcClientCacheClass =
Class.forName("org.apache.shenyu.plugin.grpc.cache.GrpcClientCache");
Field clientCacheField =
grpcClientCacheClass.getDeclaredField("CLIENT_CACHE");
@@ -120,6 +149,7 @@ public class GrpcPluginTest {
when(mockClient.call(Mockito.any(), Mockito.any(), Mockito.any(),
Mockito.any()))
.thenAnswer(invocation -> {
assertEquals(expectedRemoteAddress,
GrpcConstants.GRPC_REMOTE_ADDRESS.get());
+ assertEquals(expectedMethodType,
invocation.getArgument(3));
return CompletableFuture.completedFuture(response);
});
clientCacheMap.put("grpcId", mockClient);
@@ -171,7 +201,7 @@ public class GrpcPluginTest {
.serviceName("echo.EchoService")
.methodName("echo")
.rpcType(RpcTypeEnum.GRPC.getName())
- .rpcExt("{timeout:5000}")
+
.rpcExt("{\"timeout\":5000,\"methodType\":\"SERVER_STREAMING\"}")
.parameterTypes("param")
.enabled(true).build();
}