diff --git a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java index 6bac938c72..391ad158a9 100644 --- a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java +++ b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java @@ -93,6 +93,14 @@ public class HubConnection { this.tickRate = tickRateInMilliseconds; } + TransportEnum getTransportEnum() { + return this.transportEnum; + } + + Transport getTransport() { + return transport; + } + HubConnection(String url, Transport transport, boolean skipNegotiate, HttpClient httpClient, Single accessTokenProvider, long handshakeResponseTimeout, Map headers, TransportEnum transportEnum) { if (url == null || url.isEmpty()) { @@ -235,7 +243,8 @@ public class HubConnection { return httpClient.post(Negotiate.resolveNegotiateUrl(url), request).map((response) -> { if (response.getStatusCode() != 200) { - throw new RuntimeException(String.format("Unexpected status code returned from negotiate: %d %s.", response.getStatusCode(), response.getStatusText())); + throw new RuntimeException(String.format("Unexpected status code returned from negotiate: %d %s.", + response.getStatusCode(), response.getStatusText())); } NegotiateResponse negotiateResponse = new NegotiateResponse(response.getContent()); @@ -377,8 +386,15 @@ public class HubConnection { if (response.getRedirectUrl() == null) { Set transports = response.getAvailableTransports(); - if ((this.transportEnum == TransportEnum.ALL && !(transports.contains("WebSockets") || transports.contains("LongPolling"))) || - (this.transportEnum == TransportEnum.WEBSOCKETS && !transports.contains("WebSockets")) || + if (this.transportEnum == TransportEnum.ALL) { + if (transports.contains("WebSockets")) { + this.transportEnum = TransportEnum.WEBSOCKETS; + } else if (transports.contains("LongPolling")) { + this.transportEnum = TransportEnum.LONG_POLLING; + } else { + throw new RuntimeException("There were no compatible transports on the server."); + } + } else if (this.transportEnum == TransportEnum.WEBSOCKETS && !transports.contains("WebSockets") || (this.transportEnum == TransportEnum.LONG_POLLING && !transports.contains("LongPolling"))) { throw new RuntimeException("There were no compatible transports on the server."); } diff --git a/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/HubConnectionTest.java b/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/HubConnectionTest.java index 9878ad853b..f576c1c828 100644 --- a/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/HubConnectionTest.java +++ b/src/SignalR/clients/java/signalr/src/test/java/com/microsoft/signalr/HubConnectionTest.java @@ -11,8 +11,10 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import io.reactivex.subjects.CompletableSubject; import org.junit.jupiter.api.Test; import io.reactivex.Observable; @@ -1219,6 +1221,74 @@ class HubConnectionTest { assertEquals("{\"protocol\":\"json\",\"version\":1}" + RECORD_SEPARATOR, sentMessages[0]); } + @Test + public void TransportAllUsesLongPollingWhenServerOnlySupportLongPolling() { + AtomicInteger requestCount = new AtomicInteger(0); + TestHttpClient client = new TestHttpClient().on("POST", + (req) -> Single.just(new HttpResponse(200, "", + "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" + + "availableTransports\":[{\"transport\":\"LongPolling\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"))) + .on("GET", (req) -> { + if (requestCount.get() == 0) { + requestCount.incrementAndGet(); + return Single.just(new HttpResponse(200, "", "")); + } + return Single.just(new HttpResponse(204, "", "")); + }); + + HubConnection hubConnection = HubConnectionBuilder + .create("http://example.com") + .withTransport(TransportEnum.ALL) + .withHttpClient(client) + .build(); + + hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait(); + assertTrue(hubConnection.getTransport() instanceof LongPollingTransport); + hubConnection.stop().timeout(1, TimeUnit.SECONDS).blockingAwait(); + } + + @Test + public void ClientThatSelectsWebsocketsThrowsWhenWebsocketsAreNotAvailable() { + TestHttpClient client = new TestHttpClient().on("POST", + (req) -> Single.just(new HttpResponse(200, "", + "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" + + "availableTransports\":[{\"transport\":\"LongPolling\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"))) + .on("GET", (req) -> { + return Single.just(new HttpResponse(204, "", "")); + }); + + HubConnection hubConnection = HubConnectionBuilder + .create("http://example.com") + .withTransport(TransportEnum.WEBSOCKETS) + .withHttpClient(client) + .build(); + + assertEquals(TransportEnum.WEBSOCKETS, hubConnection.getTransportEnum()); + RuntimeException exception = assertThrows(RuntimeException.class, + () -> hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait()); + + assertEquals(exception.getMessage(), "There were no compatible transports on the server."); + } + + @Test + public void ClientThatSelectsLongPollingThrowsWhenLongPollingIsNotAvailable() { + TestHttpClient client = new TestHttpClient().on("POST", + (req) -> Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" + + "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"))); + + HubConnection hubConnection = HubConnectionBuilder + .create("http://example.com") + .withTransport(TransportEnum.LONG_POLLING) + .withHttpClient(client) + .build(); + + assertEquals(TransportEnum.LONG_POLLING, hubConnection.getTransportEnum()); + RuntimeException exception = assertThrows(RuntimeException.class, + () -> hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait()); + + assertEquals(exception.getMessage(), "There were no compatible transports on the server."); + } + @Test public void receivingServerSentEventsTransportFromNegotiateFails() { TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate",