This is an automated email from the ASF dual-hosted git repository.

dengliming 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 da0be74939 fix: prevent NPE when gRPC remote address is null (#7066)
da0be74939 is described below

commit da0be74939899e1bf10d287fd27f57d206cb175a
Author: Southern <[email protected]>
AuthorDate: Thu Sep 17 14:35:25 2026 +0800

    fix: prevent NPE when gRPC remote address is null (#7066)
    
    - Guard remote address extraction in GrpcPlugin with Optional.
      - Fall back to an empty string when the remote address or resolved 
InetAddress is null.
      - Add unit tests covering valid and null remote addresses.
      - Fix the gRPC client cache key in the existing execution test.
    
    Co-authored-by: Liming Deng <[email protected]>
---
 .../org/apache/shenyu/plugin/grpc/GrpcPlugin.java  |  7 +++-
 .../apache/shenyu/plugin/grpc/GrpcPluginTest.java  | 41 +++++++++++++++++++---
 2 files changed, 43 insertions(+), 5 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 a1b6bc516c..4be1aa32c4 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
@@ -47,6 +47,8 @@ import org.springframework.http.HttpStatus;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
 
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
@@ -97,7 +99,10 @@ public class GrpcPlugin extends AbstractShenyuPlugin {
         Context.current().withValue(GrpcConstants.GRPC_SELECTOR_ID, 
selector.getId()).attach();
         Context.current().withValue(GrpcConstants.GRPC_RULE_ID, 
rule.getId()).attach();
         Context.current().withValue(GrpcConstants.GRPC_REMOTE_ADDRESS,
-                
Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress()).attach();
+                Optional.ofNullable(exchange.getRequest().getRemoteAddress())
+                        .map(InetSocketAddress::getAddress)
+                        .map(InetAddress::getHostAddress)
+                        .orElse(StringUtils.EMPTY)).attach();
 
         GrpcExtInfo extInfo = 
GsonUtils.getGson().fromJson(metaData.getRpcExt(), GrpcExtInfo.class);
         CallOptions callOptions = 
CallOptions.DEFAULT.withDeadlineAfter(extInfo.timeout, TimeUnit.MILLISECONDS);
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 1e95bd419b..72170900df 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
@@ -28,8 +28,11 @@ import org.apache.shenyu.plugin.api.context.ShenyuContext;
 import org.apache.shenyu.plugin.api.result.DefaultShenyuResult;
 import org.apache.shenyu.plugin.api.result.ShenyuResult;
 import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
+import org.apache.shenyu.plugin.grpc.cache.GrpcClientCache;
 import org.apache.shenyu.plugin.grpc.client.ShenyuGrpcClient;
+import org.apache.shenyu.plugin.grpc.context.GrpcConstants;
 import org.apache.shenyu.plugin.grpc.proto.ShenyuGrpcResponse;
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -47,7 +50,9 @@ import reactor.core.publisher.Mono;
 import reactor.test.StepVerifier;
 
 import java.lang.reflect.Field;
+import java.net.InetSocketAddress;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -81,10 +86,27 @@ public class GrpcPluginTest {
         when(selector.getId()).thenReturn("grpcId");
     }
 
+    @AfterEach
+    public void tearDown() {
+        GrpcClientCache.removeClient("grpcId");
+    }
+
     @Test
-    @SuppressWarnings("all")
     public void testDoExecute() throws ClassNotFoundException, 
NoSuchFieldException, IllegalAccessException {
+        ServerWebExchange exchange = getServerWebExchange(new 
InetSocketAddress("127.0.0.1", 8090));
+        executeRequest(exchange, "127.0.0.1");
+    }
+
+    @Test
+    public void testDoExecuteWithNullRemoteAddress()
+            throws ClassNotFoundException, NoSuchFieldException, 
IllegalAccessException {
         ServerWebExchange exchange = getServerWebExchange();
+        executeRequest(exchange, "");
+    }
+
+    @SuppressWarnings("unchecked")
+    private void executeRequest(final ServerWebExchange exchange, final String 
expectedRemoteAddress)
+            throws ClassNotFoundException, NoSuchFieldException, 
IllegalAccessException {
         exchange.getAttributes().put(Constants.PARAM_TRANSFORM, "{message:1}");
         exchange.getAttributes().put(Constants.META_DATA, getMetaData());
 
@@ -96,8 +118,11 @@ public class GrpcPluginTest {
         ShenyuGrpcResponse response = new ShenyuGrpcResponse();
         response.getResults().add("success");
         when(mockClient.call(Mockito.any(), Mockito.any(), Mockito.any(), 
Mockito.any()))
-                .thenReturn(CompletableFuture.completedFuture(response));
-        clientCacheMap.put("/grpc", mockClient);
+                .thenAnswer(invocation -> {
+                    assertEquals(expectedRemoteAddress, 
GrpcConstants.GRPC_REMOTE_ADDRESS.get());
+                    return CompletableFuture.completedFuture(response);
+                });
+        clientCacheMap.put("grpcId", mockClient);
 
         when(chain.execute(Mockito.any())).thenReturn(Mono.empty());
         RuleData data = mock(RuleData.class);
@@ -152,7 +177,15 @@ public class GrpcPluginTest {
     }
 
     private ServerWebExchange getServerWebExchange() {
-        ServerWebExchange exchange = 
MockServerWebExchange.from(MockServerHttpRequest.get("http://localhost/grpc/echo";).build());
+        return getServerWebExchange(null);
+    }
+
+    private ServerWebExchange getServerWebExchange(final InetSocketAddress 
remoteAddress) {
+        MockServerHttpRequest.BaseBuilder<?> requestBuilder = 
MockServerHttpRequest.get("http://localhost/grpc/echo";);
+        if (Objects.nonNull(remoteAddress)) {
+            requestBuilder.remoteAddress(remoteAddress);
+        }
+        ServerWebExchange exchange = 
MockServerWebExchange.from(requestBuilder.build());
         ShenyuContext shenyuContext = mock(ShenyuContext.class);
         
when(shenyuContext.getRpcType()).thenReturn(RpcTypeEnum.GRPC.getName());
         exchange.getAttributes().put(Constants.CONTEXT, shenyuContext);

Reply via email to