Add support for negotiateVersion query string parameter and ConnectionToken (#13880)

This commit is contained in:
Mikael Mengistu 2019-09-18 14:14:26 -07:00 committed by Brennan
parent 1540b7d122
commit 9218162637
8 changed files with 165 additions and 54 deletions

View File

@ -57,6 +57,8 @@ public class HubConnection {
private Map<String, Observable> streamMap = new ConcurrentHashMap<>(); private Map<String, Observable> streamMap = new ConcurrentHashMap<>();
private TransportEnum transportEnum = TransportEnum.ALL; private TransportEnum transportEnum = TransportEnum.ALL;
private String connectionId; private String connectionId;
private String connectionToken;
private final int negotiateVersion = 1;
private final Logger logger = LoggerFactory.getLogger(HubConnection.class); private final Logger logger = LoggerFactory.getLogger(HubConnection.class);
/** /**
@ -340,11 +342,12 @@ public class HubConnection {
}); });
stopError = null; stopError = null;
String urlWithQS = Utils.appendQueryString(baseUrl, "negotiateVersion=" + negotiateVersion);
Single<NegotiateResponse> negotiate = null; Single<NegotiateResponse> negotiate = null;
if (!skipNegotiate) { if (!skipNegotiate) {
negotiate = tokenCompletable.andThen(Single.defer(() -> startNegotiate(baseUrl, 0))); negotiate = tokenCompletable.andThen(Single.defer(() -> startNegotiate(urlWithQS, 0)));
} else { } else {
negotiate = tokenCompletable.andThen(Single.defer(() -> Single.just(new NegotiateResponse(baseUrl)))); negotiate = tokenCompletable.andThen(Single.defer(() -> Single.just(new NegotiateResponse(urlWithQS))));
} }
CompletableSubject start = CompletableSubject.create(); CompletableSubject start = CompletableSubject.create();
@ -377,7 +380,6 @@ public class HubConnection {
hubConnectionStateLock.lock(); hubConnectionStateLock.lock();
try { try {
hubConnectionState = HubConnectionState.CONNECTED; hubConnectionState = HubConnectionState.CONNECTED;
this.connectionId = negotiateResponse.getConnectionId();
logger.info("HubConnection started."); logger.info("HubConnection started.");
resetServerTimeout(); resetServerTimeout();
//Don't send pings if we're using long polling. //Don't send pings if we're using long polling.
@ -447,19 +449,21 @@ public class HubConnection {
throw new RuntimeException("There were no compatible transports on the server."); throw new RuntimeException("There were no compatible transports on the server.");
} }
String finalUrl = url; if (response.getVersion() > 0) {
if (response.getConnectionId() != null) { this.connectionId = response.getConnectionId();
if (url.contains("?")) { this.connectionToken = response.getConnectionToken();
finalUrl = url + "&id=" + response.getConnectionId(); } else {
} else { this.connectionToken = this.connectionId = response.getConnectionId();
finalUrl = url + "?id=" + response.getConnectionId();
}
} }
String finalUrl = Utils.appendQueryString(url, "id=" + this.connectionToken);
response.setFinalUrl(finalUrl); response.setFinalUrl(finalUrl);
return Single.just(response); return Single.just(response);
} }
return startNegotiate(response.getRedirectUrl(), negotiateAttempts + 1); String redirectUrl = Utils.appendQueryString(response.getRedirectUrl(), "negotiateVersion=" + negotiateVersion);
return startNegotiate(redirectUrl, negotiateAttempts + 1);
}); });
} }
@ -521,6 +525,7 @@ public class HubConnection {
handshakeResponseSubject.onComplete(); handshakeResponseSubject.onComplete();
redirectAccessTokenProvider = null; redirectAccessTokenProvider = null;
connectionId = null; connectionId = null;
connectionToken = null;
transportEnum = TransportEnum.ALL; transportEnum = TransportEnum.ALL;
this.localHeaders.clear(); this.localHeaders.clear();
this.streamMap.clear(); this.streamMap.clear();

View File

@ -10,7 +10,7 @@ class Negotiate {
// Check if we have a query string. If we do then we ignore it for now. // Check if we have a query string. If we do then we ignore it for now.
int queryStringIndex = url.indexOf('?'); int queryStringIndex = url.indexOf('?');
if (queryStringIndex > 0) { if (queryStringIndex > 0) {
negotiateUrl = url.substring(0, url.indexOf('?')); negotiateUrl = url.substring(0, queryStringIndex);
} else { } else {
negotiateUrl = url; negotiateUrl = url;
} }
@ -24,7 +24,7 @@ class Negotiate {
// Add the query string back if it existed. // Add the query string back if it existed.
if (queryStringIndex > 0) { if (queryStringIndex > 0) {
negotiateUrl += url.substring(url.indexOf('?')); negotiateUrl += url.substring(queryStringIndex);
} }
return negotiateUrl; return negotiateUrl;

View File

@ -11,11 +11,13 @@ import com.google.gson.stream.JsonReader;
class NegotiateResponse { class NegotiateResponse {
private String connectionId; private String connectionId;
private String connectionToken;
private Set<String> availableTransports = new HashSet<>(); private Set<String> availableTransports = new HashSet<>();
private String redirectUrl; private String redirectUrl;
private String accessToken; private String accessToken;
private String error; private String error;
private String finalUrl; private String finalUrl;
private int version;
public NegotiateResponse(JsonReader reader) { public NegotiateResponse(JsonReader reader) {
try { try {
@ -30,6 +32,12 @@ class NegotiateResponse {
case "ProtocolVersion": case "ProtocolVersion":
this.error = "Detected an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details."; this.error = "Detected an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.";
return; return;
case "negotiateVersion":
this.version = reader.nextInt();
break;
case "connectionToken":
this.connectionToken = reader.nextString();
break;
case "url": case "url":
this.redirectUrl = reader.nextString(); this.redirectUrl = reader.nextString();
break; break;
@ -106,6 +114,14 @@ class NegotiateResponse {
return finalUrl; return finalUrl;
} }
public int getVersion() {
return version;
}
public String getConnectionToken() {
return connectionToken;
}
public void setFinalUrl(String url) { public void setFinalUrl(String url) {
this.finalUrl = url; this.finalUrl = url;
} }

View File

@ -0,0 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
package com.microsoft.signalr;
class Utils {
public static String appendQueryString(String original, String queryStringValue) {
if (original.contains("?")) {
return original + "&" + queryStringValue;
} else {
return original + "?" + queryStringValue;
}
}
}

View File

@ -1,4 +1,3 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

View File

@ -1714,12 +1714,12 @@ class HubConnectionTest {
List<HttpRequest> sentRequests = client.getSentRequests(); List<HttpRequest> sentRequests = client.getSentRequests();
assertEquals(1, sentRequests.size()); assertEquals(1, sentRequests.size());
assertEquals("http://example.com/negotiate", sentRequests.get(0).getUrl()); assertEquals("http://example.com/negotiate?negotiateVersion=1", sentRequests.get(0).getUrl());
} }
@Test @Test
public void negotiateThatRedirectsForeverFailsAfter100Tries() { public void negotiateThatRedirectsForeverFailsAfter100Tries() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate", TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "", "{\"url\":\"http://example.com\"}"))); (req) -> Single.just(new HttpResponse(200, "", "{\"url\":\"http://example.com\"}")));
HubConnection hubConnection = HubConnectionBuilder HubConnection hubConnection = HubConnectionBuilder
@ -1752,7 +1752,7 @@ class HubConnectionTest {
@Test @Test
public void connectionIdIsAvailableAfterStart() { public void connectionIdIsAvailableAfterStart() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate", TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "", (req) -> Single.just(new HttpResponse(200, "",
"{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"))); + "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")));
@ -1775,9 +1775,62 @@ class HubConnectionTest {
assertNull(hubConnection.getConnectionId()); assertNull(hubConnection.getConnectionId());
} }
@Test
public void connectionTokenAppearsInQSConnectionIdIsOnConnectionInstance() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "",
"{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\"," +
"\"negotiateVersion\": 1," +
"\"connectionToken\":\"connection-token-value\"," +
"\"availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")));
MockTransport transport = new MockTransport(true);
HubConnection hubConnection = HubConnectionBuilder
.create("http://example.com")
.withTransportImplementation(transport)
.withHttpClient(client)
.build();
assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState());
assertNull(hubConnection.getConnectionId());
hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait();
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
assertEquals("bVOiRPG8-6YiJ6d7ZcTOVQ", hubConnection.getConnectionId());
assertEquals("http://example.com?negotiateVersion=1&id=connection-token-value", transport.getUrl());
hubConnection.stop().timeout(1, TimeUnit.SECONDS).blockingAwait();
assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState());
assertNull(hubConnection.getConnectionId());
}
@Test
public void connectionTokenIsIgnoredIfNegotiateVersionIsNotPresentInNegotiateResponse() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "",
"{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\"," +
"\"connectionToken\":\"connection-token-value\"," +
"\"availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")));
MockTransport transport = new MockTransport(true);
HubConnection hubConnection = HubConnectionBuilder
.create("http://example.com")
.withTransportImplementation(transport)
.withHttpClient(client)
.build();
assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState());
assertNull(hubConnection.getConnectionId());
hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait();
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
assertEquals("bVOiRPG8-6YiJ6d7ZcTOVQ", hubConnection.getConnectionId());
assertEquals("http://example.com?negotiateVersion=1&id=bVOiRPG8-6YiJ6d7ZcTOVQ", transport.getUrl());
hubConnection.stop().timeout(1, TimeUnit.SECONDS).blockingAwait();
assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState());
assertNull(hubConnection.getConnectionId());
}
@Test @Test
public void afterSuccessfulNegotiateConnectsWithWebsocketsTransport() { public void afterSuccessfulNegotiateConnectsWithWebsocketsTransport() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate", TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "", (req) -> Single.just(new HttpResponse(200, "",
"{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"))); + "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")));
@ -1798,7 +1851,7 @@ class HubConnectionTest {
@Test @Test
public void afterSuccessfulNegotiateConnectsWithLongPollingTransport() { public void afterSuccessfulNegotiateConnectsWithLongPollingTransport() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate", TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "", (req) -> Single.just(new HttpResponse(200, "",
"{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"LongPolling\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"))); + "availableTransports\":[{\"transport\":\"LongPolling\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")));
@ -1891,7 +1944,7 @@ class HubConnectionTest {
@Test @Test
public void receivingServerSentEventsTransportFromNegotiateFails() { public void receivingServerSentEventsTransportFromNegotiateFails() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate", TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "", (req) -> Single.just(new HttpResponse(200, "",
"{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"ServerSentEvents\",\"transferFormats\":[\"Text\"]}]}"))); + "availableTransports\":[{\"transport\":\"ServerSentEvents\",\"transferFormats\":[\"Text\"]}]}")));
@ -1911,7 +1964,7 @@ class HubConnectionTest {
@Test @Test
public void negotiateThatReturnsErrorThrowsFromStart() { public void negotiateThatReturnsErrorThrowsFromStart() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate", TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "", "{\"error\":\"Test error.\"}"))); (req) -> Single.just(new HttpResponse(200, "", "{\"error\":\"Test error.\"}")));
MockTransport transport = new MockTransport(true); MockTransport transport = new MockTransport(true);
@ -1928,7 +1981,7 @@ class HubConnectionTest {
@Test @Test
public void DetectWhenTryingToConnectToClassicSignalRServer() { public void DetectWhenTryingToConnectToClassicSignalRServer() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate", TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "", "{\"Url\":\"/signalr\"," + (req) -> Single.just(new HttpResponse(200, "", "{\"Url\":\"/signalr\"," +
"\"ConnectionToken\":\"X97dw3uxW4NPPggQsYVcNcyQcuz4w2\"," + "\"ConnectionToken\":\"X97dw3uxW4NPPggQsYVcNcyQcuz4w2\"," +
"\"ConnectionId\":\"05265228-1e2c-46c5-82a1-6a5bcc3f0143\"," + "\"ConnectionId\":\"05265228-1e2c-46c5-82a1-6a5bcc3f0143\"," +
@ -1954,9 +2007,9 @@ class HubConnectionTest {
@Test @Test
public void negotiateRedirectIsFollowed() { public void negotiateRedirectIsFollowed() {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate", TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\"}"))) (req) -> Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\"}")))
.on("POST", "http://testexample.com/negotiate", .on("POST", "http://testexample.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" (req) -> Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"))); + "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")));
@ -1978,11 +2031,11 @@ class HubConnectionTest {
AtomicReference<String> beforeRedirectToken = new AtomicReference<>(); AtomicReference<String> beforeRedirectToken = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", (req) -> { .on("POST", "http://example.com/negotiate?negotiateVersion=1", (req) -> {
beforeRedirectToken.set(req.getHeaders().get("Authorization")); beforeRedirectToken.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"newToken\"}")); return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"newToken\"}"));
}) })
.on("POST", "http://testexample.com/negotiate", (req) -> { .on("POST", "http://testexample.com/negotiate?negotiateVersion=1", (req) -> {
token.set(req.getHeaders().get("Authorization")); token.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")); + "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"));
@ -2018,7 +2071,7 @@ class HubConnectionTest {
public void accessTokenProviderIsUsedForNegotiate() { public void accessTokenProviderIsUsedForNegotiate() {
AtomicReference<String> token = new AtomicReference<>(); AtomicReference<String> token = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", .on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> { (req) -> {
token.set(req.getHeaders().get("Authorization")); token.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
@ -2043,11 +2096,13 @@ class HubConnectionTest {
public void accessTokenProviderIsOverriddenFromRedirectNegotiate() { public void accessTokenProviderIsOverriddenFromRedirectNegotiate() {
AtomicReference<String> token = new AtomicReference<>(); AtomicReference<String> token = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", (req) -> Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"newToken\"}"))) .on("POST", "http://example.com/negotiate?negotiateVersion=1", (req) -> Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"newToken\"}")))
.on("POST", "http://testexample.com/negotiate", (req) -> { .on("POST", "http://testexample.com/negotiate?negotiateVersion=1", (req) -> {
token.set(req.getHeaders().get("Authorization")); token.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\","
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")); + "\"connectionToken\":\"connection-token-value\","
+ "\"negotiateVersion\":1,"
+ "\"availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"));
}); });
MockTransport transport = new MockTransport(true); MockTransport transport = new MockTransport(true);
@ -2060,7 +2115,7 @@ class HubConnectionTest {
hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait(); hubConnection.start().timeout(1, TimeUnit.SECONDS).blockingAwait();
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
assertEquals("http://testexample.com/?id=bVOiRPG8-6YiJ6d7ZcTOVQ", transport.getUrl()); assertEquals("http://testexample.com/?negotiateVersion=1&id=connection-token-value", transport.getUrl());
hubConnection.stop(); hubConnection.stop();
assertEquals("Bearer newToken", token.get()); assertEquals("Bearer newToken", token.get());
} }
@ -2071,14 +2126,14 @@ class HubConnectionTest {
AtomicReference<String> beforeRedirectToken = new AtomicReference<>(); AtomicReference<String> beforeRedirectToken = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", (req) -> { .on("POST", "http://example.com/negotiate?negotiateVersion=1", (req) -> {
beforeRedirectToken.set(req.getHeaders().get("Authorization")); beforeRedirectToken.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"newToken\"}")); return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"newToken\"}"));
}) })
.on("POST", "http://testexample.com/negotiate", (req) -> { .on("POST", "http://testexample.com/negotiate?negotiateVersion=1", (req) -> {
token.set(req.getHeaders().get("Authorization")); token.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\","
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")); + "\"availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"));
}); });
MockTransport transport = new MockTransport(true); MockTransport transport = new MockTransport(true);
@ -2112,7 +2167,7 @@ class HubConnectionTest {
AtomicInteger redirectCount = new AtomicInteger(); AtomicInteger redirectCount = new AtomicInteger();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", (req) -> { .on("POST", "http://example.com/negotiate?negotiateVersion=1", (req) -> {
if (redirectCount.get() == 0) { if (redirectCount.get() == 0) {
redirectCount.incrementAndGet(); redirectCount.incrementAndGet();
redirectToken.set(req.getHeaders().get("Authorization")); redirectToken.set(req.getHeaders().get("Authorization"));
@ -2122,7 +2177,7 @@ class HubConnectionTest {
return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"secondRedirectToken\"}")); return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"secondRedirectToken\"}"));
} }
}) })
.on("POST", "http://testexample.com/negotiate", (req) -> { .on("POST", "http://testexample.com/negotiate?negotiateVersion=1", (req) -> {
token.set(req.getHeaders().get("Authorization")); token.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")); + "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"));
@ -2189,7 +2244,7 @@ class HubConnectionTest {
public void userAgentHeaderIsSet() { public void userAgentHeaderIsSet() {
AtomicReference<String> header = new AtomicReference<>(); AtomicReference<String> header = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", .on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> { (req) -> {
header.set(req.getHeaders().get("User-Agent")); header.set(req.getHeaders().get("User-Agent"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
@ -2213,7 +2268,7 @@ class HubConnectionTest {
public void userAgentHeaderCanBeOverwritten() { public void userAgentHeaderCanBeOverwritten() {
AtomicReference<String> header = new AtomicReference<>(); AtomicReference<String> header = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", .on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> { (req) -> {
header.set(req.getHeaders().get("User-Agent")); header.set(req.getHeaders().get("User-Agent"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
@ -2237,7 +2292,7 @@ class HubConnectionTest {
public void userAgentCanBeCleared() { public void userAgentCanBeCleared() {
AtomicReference<String> header = new AtomicReference<>(); AtomicReference<String> header = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", .on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> { (req) -> {
header.set(req.getHeaders().get("User-Agent")); header.set(req.getHeaders().get("User-Agent"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
@ -2260,7 +2315,7 @@ class HubConnectionTest {
public void headersAreSetAndSentThroughBuilder() { public void headersAreSetAndSentThroughBuilder() {
AtomicReference<String> header = new AtomicReference<>(); AtomicReference<String> header = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", .on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> { (req) -> {
header.set(req.getHeaders().get("ExampleHeader")); header.set(req.getHeaders().get("ExampleHeader"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
@ -2285,7 +2340,7 @@ class HubConnectionTest {
public void headersAreNotClearedWhenConnectionIsRestarted() { public void headersAreNotClearedWhenConnectionIsRestarted() {
AtomicReference<String> header = new AtomicReference<>(); AtomicReference<String> header = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", .on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> { (req) -> {
header.set(req.getHeaders().get("Authorization")); header.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
@ -2315,12 +2370,12 @@ class HubConnectionTest {
AtomicReference<String> afterRedirectHeader = new AtomicReference<>(); AtomicReference<String> afterRedirectHeader = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", .on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> { (req) -> {
beforeRedirectHeader.set(req.getHeaders().get("Authorization")); beforeRedirectHeader.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"redirectToken\"}\"}")); return Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"redirectToken\"}\"}"));
}) })
.on("POST", "http://testexample.com/negotiate", .on("POST", "http://testexample.com/negotiate?negotiateVersion=1",
(req) -> { (req) -> {
afterRedirectHeader.set(req.getHeaders().get("Authorization")); afterRedirectHeader.set(req.getHeaders().get("Authorization"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
@ -2358,7 +2413,7 @@ class HubConnectionTest {
public void sameHeaderSetTwiceGetsOverwritten() { public void sameHeaderSetTwiceGetsOverwritten() {
AtomicReference<String> header = new AtomicReference<>(); AtomicReference<String> header = new AtomicReference<>();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", .on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> { (req) -> {
header.set(req.getHeaders().get("ExampleHeader")); header.set(req.getHeaders().get("ExampleHeader"));
return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" return Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
@ -2403,8 +2458,8 @@ class HubConnectionTest {
public void hubConnectionCanBeStartedAfterBeingStoppedAndRedirected() { public void hubConnectionCanBeStartedAfterBeingStoppedAndRedirected() {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", (req) -> Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\"}"))) .on("POST", "http://example.com/negotiate?negotiateVersion=1", (req) -> Single.just(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\"}")))
.on("POST", "http://testexample.com/negotiate", (req) -> Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" .on("POST", "http://testexample.com/negotiate?negotiateVersion=1", (req) -> Single.just(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"))); + "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")));
HubConnection hubConnection = HubConnectionBuilder HubConnection hubConnection = HubConnectionBuilder
@ -2426,7 +2481,7 @@ class HubConnectionTest {
@Test @Test
public void non200FromNegotiateThrowsError() { public void non200FromNegotiateThrowsError() {
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", .on("POST", "http://example.com/negotiate?negotiateVersion=1",
(req) -> Single.just(new HttpResponse(500, "Internal server error", ""))); (req) -> Single.just(new HttpResponse(500, "Internal server error", "")));
MockTransport transport = new MockTransport(); MockTransport transport = new MockTransport();

View File

@ -15,8 +15,9 @@ import com.google.gson.stream.JsonReader;
class NegotiateResponseTest { class NegotiateResponseTest {
@Test @Test
public void VerifyNegotiateResponse() { public void VerifyNegotiateResponse() {
String stringNegotiateResponse = "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" + String stringNegotiateResponse = "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\"," +
"availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}," + "\"negotiateVersion\": 99, \"connectionToken\":\"connection-token-value\"," +
"\"availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}," +
"{\"transport\":\"ServerSentEvents\",\"transferFormats\":[\"Text\"]}," + "{\"transport\":\"ServerSentEvents\",\"transferFormats\":[\"Text\"]}," +
"{\"transport\":\"LongPolling\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"; "{\"transport\":\"LongPolling\",\"transferFormats\":[\"Text\",\"Binary\"]}]}";
NegotiateResponse negotiateResponse = new NegotiateResponse(new JsonReader(new StringReader(stringNegotiateResponse))); NegotiateResponse negotiateResponse = new NegotiateResponse(new JsonReader(new StringReader(stringNegotiateResponse)));
@ -26,6 +27,8 @@ class NegotiateResponseTest {
assertNull(negotiateResponse.getAccessToken()); assertNull(negotiateResponse.getAccessToken());
assertNull(negotiateResponse.getRedirectUrl()); assertNull(negotiateResponse.getRedirectUrl());
assertEquals("bVOiRPG8-6YiJ6d7ZcTOVQ", negotiateResponse.getConnectionId()); assertEquals("bVOiRPG8-6YiJ6d7ZcTOVQ", negotiateResponse.getConnectionId());
assertEquals("connection-token-value", negotiateResponse.getConnectionToken());
assertEquals(99, negotiateResponse.getVersion());
} }
@Test @Test
@ -56,4 +59,23 @@ class NegotiateResponseTest {
NegotiateResponse negotiateResponse = new NegotiateResponse(new JsonReader(new StringReader(stringNegotiateResponse))); NegotiateResponse negotiateResponse = new NegotiateResponse(new JsonReader(new StringReader(stringNegotiateResponse)));
assertEquals("bVOiRPG8-6YiJ6d7ZcTOVQ", negotiateResponse.getConnectionId()); assertEquals("bVOiRPG8-6YiJ6d7ZcTOVQ", negotiateResponse.getConnectionId());
} }
@Test
public void NegotiateResponseWithNegotiateVersion() {
String stringNegotiateResponse = "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\"," +
"\"negotiateVersion\": 99}";
NegotiateResponse negotiateResponse = new NegotiateResponse(new JsonReader(new StringReader(stringNegotiateResponse)));
assertEquals("bVOiRPG8-6YiJ6d7ZcTOVQ", negotiateResponse.getConnectionId());
assertEquals(99, negotiateResponse.getVersion());
}
@Test
public void NegotiateResponseWithConnectionToken() {
String stringNegotiateResponse = "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\"," +
"\"negotiateVersion\": 99, \"connectionToken\":\"connection-token-value\"}";
NegotiateResponse negotiateResponse = new NegotiateResponse(new JsonReader(new StringReader(stringNegotiateResponse)));
assertEquals("bVOiRPG8-6YiJ6d7ZcTOVQ", negotiateResponse.getConnectionId());
assertEquals("connection-token-value", negotiateResponse.getConnectionToken());
assertEquals(99, negotiateResponse.getVersion());
}
} }

View File

@ -30,17 +30,17 @@ public class UserAgentTest {
} }
@Test @Test
public void verifyJavaVendor(){ public void verifyJavaVendor() {
assertEquals(System.getProperty("java.vendor"), UserAgentHelper.getJavaVendor()); assertEquals(System.getProperty("java.vendor"), UserAgentHelper.getJavaVendor());
} }
@Test @Test
public void verifyJavaVersion(){ public void verifyJavaVersion() {
assertEquals(System.getProperty("java.version"), UserAgentHelper.getJavaVersion()); assertEquals(System.getProperty("java.version"), UserAgentHelper.getJavaVersion());
} }
@Test @Test
public void checkUserAgentString(){ public void checkUserAgentString() {
String userAgent = UserAgentHelper.createUserAgentString(); String userAgent = UserAgentHelper.createUserAgentString();
assertNotNull(userAgent); assertNotNull(userAgent);