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 e6523de8c5 fix: avoid copying unused request data in LoadbalancerUtils 
(#6578) (#7431)
e6523de8c5 is described below

commit e6523de8c5e2daefac76337b8d1caee99ddf36cd
Author: wy471x <[email protected]>
AuthorDate: Thu Oct 8 14:46:54 2026 +0800

    fix: avoid copying unused request data in LoadbalancerUtils (#6578) (#7431)
---
 .../loadbalancer/entity/LoadBalanceData.java       | 10 ++--
 .../loadbalancer/entity/LoadBalanceDataTest.java   | 68 ++++++++++++++++++++++
 .../plugin/base/utils/LoadbalancerUtils.java       | 36 +++---------
 .../plugin/base/utils/LoadbalancerUtilsTest.java   | 31 ++++++++--
 4 files changed, 106 insertions(+), 39 deletions(-)

diff --git 
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceData.java
 
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceData.java
index b06ba56813..9a37d9cf31 100644
--- 
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceData.java
+++ 
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceData.java
@@ -19,7 +19,7 @@ package org.apache.shenyu.loadbalancer.entity;
 
 import java.net.URI;
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.Map;
 
 /**
@@ -33,13 +33,13 @@ public class LoadBalanceData {
     
     private URI url;
     
-    private Map<String, Collection<String>> headers = new HashMap<>();
+    private Map<String, Collection<String>> headers = Collections.emptyMap();
     
-    private Map<String, String> cookies = new HashMap<>();
+    private Map<String, String> cookies = Collections.emptyMap();
     
-    private Map<String, Object> attributes = new HashMap<>();
+    private Map<String, Object> attributes = Collections.emptyMap();
     
-    private Map<String, Collection<String>> queryParams = new HashMap<>();
+    private Map<String, Collection<String>> queryParams = 
Collections.emptyMap();
     
     /**
      * Instantiates a new Load balance data.
diff --git 
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceDataTest.java
 
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceDataTest.java
new file mode 100644
index 0000000000..87f5743fc9
--- /dev/null
+++ 
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceDataTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.loadbalancer.entity;
+
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Test cases for LoadBalanceData.
+ */
+class LoadBalanceDataTest {
+
+    @Test
+    void defaultInstanceUsesSharedEmptyCollections() {
+        LoadBalanceData data = new LoadBalanceData();
+        assertEquals("GET", data.getHttpMethod());
+        assertEquals("127.0.0.1", data.getIp());
+        assertTrue(data.getHeaders().isEmpty());
+        assertTrue(data.getCookies().isEmpty());
+        assertTrue(data.getAttributes().isEmpty());
+        assertTrue(data.getQueryParams().isEmpty());
+        LoadBalanceData another = new LoadBalanceData();
+        assertSame(data.getHeaders(), another.getHeaders());
+        assertSame(data.getCookies(), another.getCookies());
+        assertSame(data.getAttributes(), another.getAttributes());
+        assertSame(data.getQueryParams(), another.getQueryParams());
+    }
+
+    @Test
+    void fullConstructorKeepsProvidedValues() {
+        Map<String, Collection<String>> headers = 
Collections.singletonMap("key", Collections.singletonList("value"));
+        Map<String, String> cookies = Collections.singletonMap("cookie", 
"value");
+        Map<String, Object> attributes = Collections.singletonMap("attribute", 
new Object());
+        Map<String, Collection<String>> queryParams = 
Collections.singletonMap("param", Collections.singletonList("value"));
+        LoadBalanceData data = new LoadBalanceData("POST", "1.2.3.4", 
URI.create("http://localhost";),
+                headers, cookies, attributes, queryParams);
+        assertEquals("POST", data.getHttpMethod());
+        assertEquals("1.2.3.4", data.getIp());
+        assertEquals(URI.create("http://localhost";), data.getUrl());
+        assertSame(headers, data.getHeaders());
+        assertSame(cookies, data.getCookies());
+        assertSame(attributes, data.getAttributes());
+        assertSame(queryParams, data.getQueryParams());
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtils.java
 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtils.java
index 46acbba76c..cfcba20648 100644
--- 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtils.java
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtils.java
@@ -17,19 +17,14 @@
 
 package org.apache.shenyu.plugin.base.utils;
 
-import org.apache.commons.collections4.MapUtils;
 import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
 import org.apache.shenyu.loadbalancer.entity.Upstream;
 import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
-import org.springframework.http.HttpCookie;
-import org.springframework.http.HttpHeaders;
 import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.util.MultiValueMap;
 import org.springframework.web.server.ServerWebExchange;
 
 import java.net.URI;
-import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -73,31 +68,14 @@ public final class LoadbalancerUtils {
                 .map(address -> address.getHostAddress())
                 .orElse("127.0.0.1");
         String httpMethod = 
Optional.ofNullable(request.getMethod()).map(method -> 
method.name()).orElse("GET");
-        URI uri = exchange.getRequest().getURI();
-        HttpHeaders headers = request.getHeaders();
-        MultiValueMap<String, HttpCookie> cookies = request.getCookies();
+        URI uri = request.getURI();
         Map<String, Object> attributes = exchange.getAttributes();
-        MultiValueMap<String, String> queryParams = request.getQueryParams();
+        // Only the ip is read by a load balancer (hash); copying headers, 
cookies and query
+        // params here would allocate maps per request without any consumer.
         return new LoadBalanceData(httpMethod, ip, uri,
-                buildMultiValueMap(headers),
-                buildCookies(cookies),
+                Collections.emptyMap(),
+                Collections.emptyMap(),
                 attributes,
-                buildMultiValueMap(queryParams));
-    }
-    
-    private static Map<String, Collection<String>> buildMultiValueMap(final 
MultiValueMap<String, String> queryParams) {
-        Map<String, Collection<String>> resultMap = new HashMap<>();
-        if (MapUtils.isNotEmpty(queryParams)) {
-            resultMap.putAll(queryParams);
-        }
-        return resultMap;
-    }
-    
-    private static Map<String, String> buildCookies(final 
MultiValueMap<String, HttpCookie> cookies) {
-        Map<String, String> resultMap = new HashMap<>();
-        if (MapUtils.isNotEmpty(cookies)) {
-            cookies.forEach((key, value) -> value.forEach((cookie) -> 
resultMap.put(cookie.getName(), cookie.getValue())));
-        }
-        return resultMap;
+                Collections.emptyMap());
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtilsTest.java
 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtilsTest.java
index a2d8f27af1..1a35cc8971 100644
--- 
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtilsTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtilsTest.java
@@ -20,17 +20,21 @@ package org.apache.shenyu.plugin.base.utils;
 import org.apache.shenyu.common.enums.LoadBalanceEnum;
 import org.apache.shenyu.loadbalancer.entity.Upstream;
 import org.junit.jupiter.api.Test;
-import org.springframework.http.HttpHeaders;
 import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.web.server.ServerWebExchange;
 
+import java.net.InetSocketAddress;
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 /**
@@ -42,9 +46,6 @@ public final class LoadbalancerUtilsTest {
     public void testMissingRemoteAddressAndMethodUseDefaults() {
         ServerHttpRequest request = mock(ServerHttpRequest.class);
         when(request.getURI()).thenReturn(URI.create("http://localhost/test";));
-        when(request.getHeaders()).thenReturn(HttpHeaders.EMPTY);
-        when(request.getCookies()).thenReturn(new LinkedMultiValueMap<>());
-        when(request.getQueryParams()).thenReturn(new LinkedMultiValueMap<>());
         ServerWebExchange exchange = mock(ServerWebExchange.class);
         when(exchange.getRequest()).thenReturn(request);
         when(exchange.getAttributes()).thenReturn(new HashMap<>());
@@ -55,4 +56,24 @@ public final class LoadbalancerUtilsTest {
 
         assertSame(upstream, selected);
     }
+
+    @Test
+    public void testGetForExchangeDoesNotCopyUnusedRequestData() {
+        ServerHttpRequest request = mock(ServerHttpRequest.class);
+        when(request.getURI()).thenReturn(URI.create("http://localhost/test";));
+        when(request.getRemoteAddress()).thenReturn(new 
InetSocketAddress("127.0.0.1", 8080));
+        ServerWebExchange exchange = mock(ServerWebExchange.class);
+        when(exchange.getRequest()).thenReturn(request);
+        when(exchange.getAttributes()).thenReturn(new HashMap<>());
+        List<Upstream> upstreamList = new ArrayList<>();
+        upstreamList.add(Upstream.builder().url("http://1.1.1.1/api";).build());
+        upstreamList.add(Upstream.builder().url("http://2.2.2.2/api";).build());
+
+        Upstream selected = LoadbalancerUtils.getForExchange(upstreamList, 
LoadBalanceEnum.HASH.getName(), exchange);
+
+        assertNotNull(selected);
+        verify(request, never()).getHeaders();
+        verify(request, never()).getCookies();
+        verify(request, never()).getQueryParams();
+    }
 }

Reply via email to