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();
     }

Reply via email to