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 436f82b6fd fix: prevent NPE in Dubbo ingress upstream parsing (#6860) 
(#7059)
436f82b6fd is described below

commit 436f82b6fd20b38ab3d96d923973fc5efcee9089
Author: Southern <[email protected]>
AuthorDate: Fri Sep 18 15:13:09 2026 +0800

    fix: prevent NPE in Dubbo ingress upstream parsing (#6860) (#7059)
    
    * fix: prevent NPE in Dubbo ingress upstream parsing (#6860)
    
      Guard null path backends and missing upstream protocol annotations in 
DubboIngressParser, and add focused tests for null
      annotations, missing annotation keys, and null backends.
    
    * fix: prevent NPE in Dubbo ingress upstream parsing (#6860)
    
      Guard null path backends and missing upstream protocol annotations in 
DubboIngressParser. Add regression tests for null
      annotations and null path backends.
    
    ---------
    
    Co-authored-by: Liming Deng <[email protected]>
---
 .../shenyu/k8s/parser/DubboIngressParser.java      |  6 ++-
 .../shenyu/k8s/parser/DubboIngressParserTest.java  | 49 ++++++++++++++++++++++
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git 
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DubboIngressParser.java
 
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DubboIngressParser.java
index 4a2e077dcd..72425a2b93 100644
--- 
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DubboIngressParser.java
+++ 
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DubboIngressParser.java
@@ -332,12 +332,14 @@ public class DubboIngressParser implements 
K8sResourceParser<V1Ingress> {
 
     private List<DubboUpstream> parseUpstream(final V1HTTPIngressPath path, 
final String namespace, final Map<String, String> annotations) {
         List<DubboUpstream> upstreamList = new ArrayList<>();
-        if (Objects.nonNull(path) && 
Objects.nonNull(path.getBackend().getService()) && 
Objects.nonNull(path.getBackend().getService().getName())) {
+        if (Objects.nonNull(path) && Objects.nonNull(path.getBackend())
+                && Objects.nonNull(path.getBackend().getService()) && 
Objects.nonNull(path.getBackend().getService().getName())) {
             String serviceName = path.getBackend().getService().getName();
             V1Endpoints v1Endpoints = 
endpointsLister.namespace(namespace).get(serviceName);
             List<V1EndpointSubset> subsets = v1Endpoints.getSubsets();
             String[] protocols = null;
-            if (Objects.nonNull(annotations) && 
annotations.containsKey(IngressConstants.UPSTREAMS_PROTOCOL_ANNOTATION_KEY)) {
+            if (Objects.nonNull(annotations) && 
annotations.containsKey(IngressConstants.UPSTREAMS_PROTOCOL_ANNOTATION_KEY)
+                    && 
Objects.nonNull(annotations.get(IngressConstants.UPSTREAMS_PROTOCOL_ANNOTATION_KEY)))
 {
                 protocols = 
annotations.get(IngressConstants.UPSTREAMS_PROTOCOL_ANNOTATION_KEY).split(",");
             }
             if (Objects.isNull(subsets) || CollectionUtils.isEmpty(subsets)) {
diff --git 
a/shenyu-kubernetes-controller/src/test/java/org/apache/shenyu/k8s/parser/DubboIngressParserTest.java
 
b/shenyu-kubernetes-controller/src/test/java/org/apache/shenyu/k8s/parser/DubboIngressParserTest.java
index b53291f074..6907b28777 100644
--- 
a/shenyu-kubernetes-controller/src/test/java/org/apache/shenyu/k8s/parser/DubboIngressParserTest.java
+++ 
b/shenyu-kubernetes-controller/src/test/java/org/apache/shenyu/k8s/parser/DubboIngressParserTest.java
@@ -32,9 +32,11 @@ import 
org.apache.shenyu.common.dto.convert.selector.DubboUpstream;
 import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.k8s.common.IngressConstants;
 import org.apache.shenyu.k8s.common.ShenyuMemoryConfig;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -51,6 +53,11 @@ import static org.mockito.Mockito.when;
  */
 public class DubboIngressParserTest {
 
+    private static final String NAMESPACE = "test-namespace";
+
+    private static final String SERVICE_NAME = "backend-service";
+
+
     private Lister<V1Service> serviceLister;
 
     private Indexer<V1Endpoints> endpointsIndexer;
@@ -152,4 +159,46 @@ public class DubboIngressParserTest {
         List<DubboUpstream> upstreams = assertDoesNotThrow(() -> 
parseAndGetUpstreams(annotations));
         assertNotNull(upstreams);
     }
+
+    @Test
+    public void shouldParseIngressWhenAnnotationsAreNull() {
+        ShenyuMemoryConfig config = assertDoesNotThrow(() -> 
createParser().parse(
+                createIngress(null, Collections.emptyMap(), true), null));
+
+        String handle = 
config.getRouteConfigList().get(0).getSelectorData().getHandle();
+        List<DubboUpstream> upstreams = 
GsonUtils.getInstance().fromList(handle, DubboUpstream.class);
+        assertEquals(1, upstreams.size());
+        assertEquals("dubbo://", upstreams.get(0).getProtocol());
+    }
+
+    @Test
+    public void shouldIgnorePathWithNullBackend() {
+        ShenyuMemoryConfig config = Assertions.assertDoesNotThrow(() -> 
createParser().parse(
+                createIngress(null, Collections.emptyMap(), false), null));
+
+        Assertions.assertEquals(1, config.getRouteConfigList().size());
+        Assertions.assertEquals("[]", 
config.getRouteConfigList().get(0).getSelectorData().getHandle());
+    }
+
+    private DubboIngressParser createParser() {
+        Indexer<V1Service> serviceIndexer = mock(Indexer.class);
+        Indexer<V1Endpoints> endpointsIndexer = mock(Indexer.class);
+        V1Endpoints endpoints = new V1EndpointsBuilder().withSubsets(new 
V1EndpointSubsetBuilder()
+                .withAddresses(new 
V1EndpointAddress().ip("127.0.0.1")).build()).build();
+        when(endpointsIndexer.getByKey(NAMESPACE + "/" + 
SERVICE_NAME)).thenReturn(endpoints);
+        return new DubboIngressParser(new Lister<>(serviceIndexer), new 
Lister<>(endpointsIndexer));
+    }
+
+    private V1Ingress createIngress(final Map<String, String> annotations, 
final Map<String, String> labels,
+                                    final boolean withBackend) {
+        V1HTTPIngressPathBuilder pathBuilder = new 
V1HTTPIngressPathBuilder().withPath("/test").withPathType("Prefix");
+        if (withBackend) {
+            
pathBuilder.withNewBackend().withNewService().withName(SERVICE_NAME).withNewPort().withNumber(8080)
+                    .endPort().endService().endBackend();
+        }
+        return new 
V1IngressBuilder().withNewMetadata().withName("test-ingress").withNamespace(NAMESPACE)
+                .withAnnotations(annotations).withLabels(labels).endMetadata()
+                .withNewSpec().withRules(new 
V1IngressRuleBuilder().withNewHttp().withPaths(pathBuilder.build())
+                        .endHttp().build()).endSpec().build();
+    }
 }

Reply via email to