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 ec1e36cd5044..75ecd3520fe8 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 @@ private void doLongPolling(final String server) { 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 db14f2d93b18..4f58d3677a06 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 @@ 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.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.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 void test() { 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(); }