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