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 0dd517f5bf fix: handle null or invalid data in HttpSyncDataService
long polling response (#6979)
0dd517f5bf is described below
commit 0dd517f5bf7438f08667a4c41afdf694728bb320
Author: Limbo <[email protected]>
AuthorDate: Sat Sep 5 14:56:13 2026 +0800
fix: handle null or invalid data in HttpSyncDataService long polling
response (#6979)
Co-authored-by: aias00 <[email protected]>
---
.../shenyu/sync/data/http/HttpSyncDataService.java | 11 ++++---
.../sync/data/http/HttpSyncDataServiceTest.java | 35 ++++++++++++++++++++++
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git
a/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java
b/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java
index ec1e36cd50..75ecd3520f 100644
---
a/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java
+++
b/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java
@@ -236,12 +236,15 @@ public class HttpSyncDataService implements
SyncDataService {
Assert.notNull(responseBody, "Resolve response body failed.");
String json = responseBody.string();
LOG.info("listener result: [{}]", json);
- JsonObject responseFromServer = GsonUtils.getGson().fromJson(json,
JsonObject.class);
- JsonElement element = responseFromServer.get("data");
- if (element.isJsonNull()) {
+ JsonElement responseFromServer =
GsonUtils.getGson().fromJson(json, JsonElement.class);
+ if (Objects.isNull(responseFromServer) ||
responseFromServer.isJsonNull()) {
return;
}
- groupJson = responseFromServer.getAsJsonArray("data");
+ JsonElement element =
responseFromServer.getAsJsonObject().get("data");
+ if (Objects.isNull(element) || element.isJsonNull()) {
+ return;
+ }
+ groupJson = element.getAsJsonArray();
} catch (IOException e) {
String message = String.format("listener configs fail,
server:[%s], %s", server, e.getMessage());
throw new ShenyuException(message, e);
diff --git
a/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java
b/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java
index db14f2d93b..4f58d3677a 100644
---
a/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java
+++
b/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.sync.data.http;
import com.github.tomakehurst.wiremock.WireMockServer;
import
com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
+import com.github.tomakehurst.wiremock.stubbing.StubMapping;
import org.apache.shenyu.common.config.ShenyuConfig;
import org.apache.shenyu.common.constant.HttpConstants;
import org.apache.shenyu.common.dto.ConfigData;
@@ -33,6 +34,7 @@ import
org.apache.shenyu.sync.data.api.ProxySelectorDataSubscriber;
import org.apache.shenyu.sync.data.api.DiscoveryUpstreamDataSubscriber;
import org.apache.shenyu.sync.data.api.AiProxyApiKeyDataSubscriber;
import org.apache.shenyu.sync.data.http.config.HttpConfig;
+import org.apache.shenyu.sync.data.http.refresh.AbstractDataRefresh;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -58,6 +60,8 @@ import static
com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
import static
com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.atLeastOnce;
@@ -90,6 +94,8 @@ public final class HttpSyncDataServiceTest {
@BeforeEach
public void before() {
+ Map<?, ?> groupCache = (Map<?, ?>)
ReflectionTestUtils.getField(AbstractDataRefresh.class, "GROUP_CACHE");
+ Objects.requireNonNull(groupCache).clear();
this.wireMockServer = new WireMockServer(
options()
.extensions(mock(ResponseTemplateTransformer.class))
@@ -165,6 +171,35 @@ public final class HttpSyncDataServiceTest {
verify(proxySelectorDataSubscriber, atLeastOnce()).refresh();
}
+ @Test
+ public void testDoLongPollingIgnoresResponseWithoutData() {
+ httpSyncDataService.close();
+ assertAll(
+ () ->
assertLongPollingResponseIgnored("{\"code\":500,\"message\":\"error\"}"),
+ () -> assertLongPollingResponseIgnored("{\"data\":null}"),
+ () -> assertLongPollingResponseIgnored("null"),
+ () -> assertLongPollingResponseIgnored("")
+ );
+ }
+
+ private void assertLongPollingResponseIgnored(final String responseBody) {
+ StubMapping stubMapping =
wireMockServer.stubFor(post(urlPathEqualTo("/configs/listener"))
+ .atPriority(1)
+ .willReturn(aResponse()
+ .withHeader(HttpHeaders.CONTENT_TYPE,
ContentType.APPLICATION_JSON.toString())
+ .withBody(responseBody)
+ .withStatus(200))
+ );
+
+ try {
+ assertDoesNotThrow(() -> {
+ ReflectionTestUtils.invokeMethod(httpSyncDataService,
"doLongPolling", getMockServerUrl());
+ });
+ } finally {
+ wireMockServer.removeStub(stubMapping);
+ }
+ }
+
private String getMockServerUrl() {
return "http://127.0.0.1:" + wireMockServer.port();
}