[Java] Add accessTokenProvider (#3046)

This commit is contained in:
BrennanConroy 2018-10-03 14:14:14 -07:00 committed by GitHub
parent 6f45d308ce
commit 2e41a7063b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 217 additions and 103 deletions

View File

@ -3,32 +3,30 @@
package com.microsoft.aspnet.signalr; package com.microsoft.aspnet.signalr;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
public class HttpConnectionOptions { public class HttpConnectionOptions {
private String url;
private Transport transport; private Transport transport;
private LogLevel loglevel; private LogLevel loglevel;
private Logger logger; private Logger logger;
private boolean skipNegotiate; private boolean skipNegotiate;
private Supplier<CompletableFuture<String>> accessTokenProvider;
private HttpClient client;
public HttpConnectionOptions() {} public HttpConnectionOptions() {}
public HttpConnectionOptions(String url, Transport transport, LogLevel logLevel, boolean skipNegotiate) { public HttpConnectionOptions(Transport transport, LogLevel logLevel, boolean skipNegotiate) {
this.url = url;
this.transport = transport; this.transport = transport;
this.skipNegotiate = skipNegotiate; this.skipNegotiate = skipNegotiate;
this.loglevel = logLevel; this.loglevel = logLevel;
} }
public HttpConnectionOptions(String url, Transport transport, Logger logger, boolean skipNegotiate) { public HttpConnectionOptions(Transport transport, Logger logger, boolean skipNegotiate) {
this.url = url;
this.transport = transport; this.transport = transport;
this.skipNegotiate = skipNegotiate; this.skipNegotiate = skipNegotiate;
this.logger = logger; this.logger = logger;
} }
public void setUrl(String url) {
this.url = url;
}
public void setTransport(Transport transport) { public void setTransport(Transport transport) {
this.transport = transport; this.transport = transport;
@ -42,10 +40,6 @@ public class HttpConnectionOptions {
this.skipNegotiate = skipNegotiate; this.skipNegotiate = skipNegotiate;
} }
public String getUrl() {
return url;
}
public Transport getTransport() { public Transport getTransport() {
return transport; return transport;
} }
@ -65,4 +59,21 @@ public class HttpConnectionOptions {
public void setLogger(Logger logger) { public void setLogger(Logger logger) {
this.logger = logger; this.logger = logger;
} }
public void setAccessTokenProvider(Supplier<CompletableFuture<String>> accessTokenProvider) {
this.accessTokenProvider = accessTokenProvider;
}
public Supplier<CompletableFuture<String>> getAccessTokenProvider() {
return accessTokenProvider;
}
// For testing purposes only
void setHttpClient(HttpClient client) {
this.client = client;
}
HttpClient getHttpClient() {
return client;
}
} }

View File

@ -14,6 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
public class HubConnection { public class HubConnection {
private String baseUrl; private String baseUrl;
@ -28,7 +29,7 @@ public class HubConnection {
private Logger logger; private Logger logger;
private List<Consumer<Exception>> onClosedCallbackList; private List<Consumer<Exception>> onClosedCallbackList;
private boolean skipNegotiate = false; private boolean skipNegotiate = false;
private String accessToken; private Supplier<CompletableFuture<String>> accessTokenProvider;
private Map<String, String> headers = new HashMap<>(); private Map<String, String> headers = new HashMap<>();
private ConnectionState connectionState = null; private ConnectionState connectionState = null;
private HttpClient httpClient; private HttpClient httpClient;
@ -36,7 +37,7 @@ public class HubConnection {
private static ArrayList<Class<?>> emptyArray = new ArrayList<>(); private static ArrayList<Class<?>> emptyArray = new ArrayList<>();
private static int MAX_NEGOTIATE_ATTEMPTS = 100; private static int MAX_NEGOTIATE_ATTEMPTS = 100;
public HubConnection(String url, Transport transport, Logger logger, boolean skipNegotiate, HttpClient client) { public HubConnection(String url, HttpConnectionOptions options) {
if (url == null || url.isEmpty()) { if (url == null || url.isEmpty()) {
throw new IllegalArgumentException("A valid url is required."); throw new IllegalArgumentException("A valid url is required.");
} }
@ -44,26 +45,31 @@ public class HubConnection {
this.baseUrl = url; this.baseUrl = url;
this.protocol = new JsonHubProtocol(); this.protocol = new JsonHubProtocol();
if (logger != null) { if (options.getAccessTokenProvider() != null) {
this.logger = logger; this.accessTokenProvider = options.getAccessTokenProvider();
} else {
this.accessTokenProvider = () -> CompletableFuture.completedFuture(null);
}
if (options.getLogger() != null) {
this.logger = options.getLogger();
} else { } else {
this.logger = new NullLogger(); this.logger = new NullLogger();
} }
if (client != null) { if (options.getHttpClient() != null) {
this.httpClient = client; this.httpClient = options.getHttpClient();
} else { } else {
this.httpClient = new DefaultHttpClient(this.logger); this.httpClient = new DefaultHttpClient(this.logger);
} }
if (transport != null) { if (options.getTransport() != null) {
this.transport = transport; this.transport = options.getTransport();
} }
this.skipNegotiate = skipNegotiate; this.skipNegotiate = options.getSkipNegotiate();
this.callback = (payload) -> { this.callback = (payload) -> {
if (!handshakeReceived) { if (!handshakeReceived) {
int handshakeLength = payload.indexOf(RECORD_SEPARATOR) + 1; int handshakeLength = payload.indexOf(RECORD_SEPARATOR) + 1;
String handshakeResponseString = payload.substring(0, handshakeLength - 1); String handshakeResponseString = payload.substring(0, handshakeLength - 1);
@ -126,7 +132,7 @@ public class HubConnection {
}; };
} }
private CompletableFuture<NegotiateResponse> handleNegotiate(String url) throws IOException, InterruptedException, ExecutionException { private CompletableFuture<NegotiateResponse> handleNegotiate(String url) {
HttpRequest request = new HttpRequest(); HttpRequest request = new HttpRequest();
request.setHeaders(this.headers); request.setHeaders(this.headers);
@ -143,7 +149,15 @@ public class HubConnection {
} }
if (negotiateResponse.getAccessToken() != null) { if (negotiateResponse.getAccessToken() != null) {
this.headers.put("Authorization", "Bearer " + negotiateResponse.getAccessToken()); this.accessTokenProvider = () -> CompletableFuture.completedFuture(negotiateResponse.getAccessToken());
String token = "";
try {
// We know the future is already completed in this case
// It's fine to call get() on it.
token = this.accessTokenProvider.get().get();
} catch (InterruptedException | ExecutionException e) {
}
this.headers.put("Authorization", "Bearer " + token);
} }
return CompletableFuture.completedFuture(negotiateResponse); return CompletableFuture.completedFuture(negotiateResponse);
@ -169,11 +183,18 @@ public class HubConnection {
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
CompletableFuture<Void> tokenFuture = accessTokenProvider.get()
.thenAccept((token) -> {
if (token != null) {
this.headers.put("Authorization", "Bearer " + token);
}
});
CompletableFuture<String> negotiate = null; CompletableFuture<String> negotiate = null;
if (!skipNegotiate) { if (!skipNegotiate) {
negotiate = startNegotiate(baseUrl, 0); negotiate = tokenFuture.thenCompose((v) -> startNegotiate(baseUrl, 0));
} else { } else {
negotiate = CompletableFuture.completedFuture(baseUrl); negotiate = tokenFuture.thenCompose((v) -> CompletableFuture.completedFuture(baseUrl));
} }
return negotiate.thenCompose((url) -> { return negotiate.thenCompose((url) -> {
@ -207,7 +228,7 @@ public class HubConnection {
}); });
} }
private CompletableFuture<String> startNegotiate(String url, int negotiateAttempts) throws IOException, InterruptedException, ExecutionException { private CompletableFuture<String> startNegotiate(String url, int negotiateAttempts) {
if (hubConnectionState != HubConnectionState.DISCONNECTED) { if (hubConnectionState != HubConnectionState.DISCONNECTED) {
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
@ -238,11 +259,7 @@ public class HubConnection {
return CompletableFuture.completedFuture(finalUrl); return CompletableFuture.completedFuture(finalUrl);
} }
try { return startNegotiate(response.getRedirectUrl(), negotiateAttempts + 1);
return startNegotiate(response.getRedirectUrl(), negotiateAttempts + 1);
} catch (IOException | InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}); });
} }

View File

@ -7,8 +7,7 @@ public class HubConnectionBuilder {
private String url; private String url;
private Transport transport; private Transport transport;
private Logger logger; private Logger logger;
private boolean skipNegotiate; private HttpConnectionOptions options = null;
private HttpClient client;
public HubConnectionBuilder withUrl(String url) { public HubConnectionBuilder withUrl(String url) {
if (url == null || url.isEmpty()) { if (url == null || url.isEmpty()) {
@ -30,13 +29,7 @@ public class HubConnectionBuilder {
public HubConnectionBuilder withUrl(String url, HttpConnectionOptions options) { public HubConnectionBuilder withUrl(String url, HttpConnectionOptions options) {
this.url = url; this.url = url;
this.transport = options.getTransport(); this.options = options;
if (options.getLogger() != null) {
this.logger = options.getLogger();
} else if (options.getLoglevel() != null) {
this.logger = new ConsoleLogger(options.getLoglevel());
}
this.skipNegotiate = options.getSkipNegotiate();
return this; return this;
} }
@ -50,16 +43,23 @@ public class HubConnectionBuilder {
return this; return this;
} }
// For testing purposes only
HubConnectionBuilder configureHttpClient(HttpClient client) {
this.client = client;
return this;
}
public HubConnection build() { public HubConnection build() {
if (this.url == null) { if (this.url == null) {
throw new RuntimeException("The 'HubConnectionBuilder.withUrl' method must be called before building the connection."); throw new RuntimeException("The 'HubConnectionBuilder.withUrl' method must be called before building the connection.");
} }
return new HubConnection(url, transport, logger, skipNegotiate, client); if (options == null) {
options = new HttpConnectionOptions();
}
if (options.getTransport() == null && this.transport != null) {
options.setTransport(this.transport);
}
if (options.getLogger() == null && options.getLoglevel() != null) {
options.setLogger(new ConsoleLogger(options.getLoglevel()));
}
if (options.getLogger() == null && this.logger != null) {
options.setLogger(this.logger);
}
return new HubConnection(url, options);
} }
} }

View File

@ -13,8 +13,7 @@ class HttpConnectionOptionsTest {
@Test @Test
public void CheckHttpConnectionOptionsFields() { public void CheckHttpConnectionOptionsFields() {
Transport mockTransport = new MockTransport(); Transport mockTransport = new MockTransport();
HttpConnectionOptions options = new HttpConnectionOptions("http://example.com", mockTransport, LogLevel.Information, true); HttpConnectionOptions options = new HttpConnectionOptions(mockTransport, LogLevel.Information, true);
assertEquals("http://example.com",options.getUrl());
assertEquals(LogLevel.Information, options.getLoglevel()); assertEquals(LogLevel.Information, options.getLoglevel());
assertTrue(options.getSkipNegotiate()); assertTrue(options.getSkipNegotiate());
assertNotNull(options.getTransport()); assertNotNull(options.getTransport());

View File

@ -21,8 +21,7 @@ class HubConnectionTest {
@Test @Test
public void checkHubConnectionState() throws Exception { public void checkHubConnectionState() throws Exception {
Transport mockTransport = new MockTransport(); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com");
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient());
hubConnection.start(); hubConnection.start();
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
@ -48,7 +47,7 @@ class HubConnectionTest {
@Test @Test
public void hubConnectionClosesAfterCloseMessage() throws Exception { public void hubConnectionClosesAfterCloseMessage() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.start(); hubConnection.start();
mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR);
@ -63,7 +62,7 @@ class HubConnectionTest {
@Test @Test
public void hubConnectionReceiveHandshakeResponseWithError() throws Exception { public void hubConnectionReceiveHandshakeResponseWithError() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.start(); hubConnection.start();
Throwable exception = assertThrows(HubException.class, () -> mockTransport.receiveMessage("{\"error\":\"Requested protocol 'messagepack' is not available.\"}" + RECORD_SEPARATOR)); Throwable exception = assertThrows(HubException.class, () -> mockTransport.receiveMessage("{\"error\":\"Requested protocol 'messagepack' is not available.\"}" + RECORD_SEPARATOR));
@ -74,7 +73,7 @@ class HubConnectionTest {
public void registeringMultipleHandlersAndBothGetTriggered() throws Exception { public void registeringMultipleHandlersAndBothGetTriggered() throws Exception {
AtomicReference<Double> value = new AtomicReference<>(0.0); AtomicReference<Double> value = new AtomicReference<>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
Action action = () -> value.getAndUpdate((val) -> val + 1); Action action = () -> value.getAndUpdate((val) -> val + 1);
hubConnection.on("inc", action); hubConnection.on("inc", action);
@ -100,7 +99,7 @@ class HubConnectionTest {
public void removeHandlerByName() throws Exception { public void removeHandlerByName() throws Exception {
AtomicReference<Double> value = new AtomicReference<>(0.0); AtomicReference<Double> value = new AtomicReference<>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
Action action = () -> value.getAndUpdate((val) -> val + 1); Action action = () -> value.getAndUpdate((val) -> val + 1);
hubConnection.on("inc", action); hubConnection.on("inc", action);
@ -127,7 +126,7 @@ class HubConnectionTest {
public void addAndRemoveHandlerImmediately() throws Exception { public void addAndRemoveHandlerImmediately() throws Exception {
AtomicReference<Double> value = new AtomicReference<>(0.0); AtomicReference<Double> value = new AtomicReference<>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
Action action = () -> value.getAndUpdate((val) -> val + 1); Action action = () -> value.getAndUpdate((val) -> val + 1);
hubConnection.on("inc", action); hubConnection.on("inc", action);
@ -152,7 +151,7 @@ class HubConnectionTest {
public void removingMultipleHandlersWithOneCallToRemove() throws Exception { public void removingMultipleHandlersWithOneCallToRemove() throws Exception {
AtomicReference<Double> value = new AtomicReference<>(0.0); AtomicReference<Double> value = new AtomicReference<>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
Action action = () -> value.getAndUpdate((val) -> val + 1); Action action = () -> value.getAndUpdate((val) -> val + 1);
Action secondAction = () -> value.getAndUpdate((val) -> val + 2); Action secondAction = () -> value.getAndUpdate((val) -> val + 2);
@ -184,7 +183,7 @@ class HubConnectionTest {
public void removeHandlerWithUnsubscribe() throws Exception { public void removeHandlerWithUnsubscribe() throws Exception {
AtomicReference<Double> value = new AtomicReference<>(0.0); AtomicReference<Double> value = new AtomicReference<>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
Action action = () -> value.getAndUpdate((val) -> val + 1); Action action = () -> value.getAndUpdate((val) -> val + 1);
Subscription subscription = hubConnection.on("inc", action); Subscription subscription = hubConnection.on("inc", action);
@ -217,7 +216,7 @@ class HubConnectionTest {
public void unsubscribeTwice() throws Exception { public void unsubscribeTwice() throws Exception {
AtomicReference<Double> value = new AtomicReference<>(0.0); AtomicReference<Double> value = new AtomicReference<>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(),true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
Action action = () -> value.getAndUpdate((val) -> val + 1); Action action = () -> value.getAndUpdate((val) -> val + 1);
Subscription subscription = hubConnection.on("inc", action); Subscription subscription = hubConnection.on("inc", action);
@ -251,7 +250,7 @@ class HubConnectionTest {
public void removeSingleHandlerWithUnsubscribe() throws Exception { public void removeSingleHandlerWithUnsubscribe() throws Exception {
AtomicReference<Double> value = new AtomicReference<>(0.0); AtomicReference<Double> value = new AtomicReference<>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
Action action = () -> value.getAndUpdate((val) -> val + 1); Action action = () -> value.getAndUpdate((val) -> val + 1);
Action secondAction = () -> value.getAndUpdate((val) -> val + 2); Action secondAction = () -> value.getAndUpdate((val) -> val + 2);
@ -281,7 +280,7 @@ class HubConnectionTest {
public void addAndRemoveHandlerImmediatelyWithSubscribe() throws Exception { public void addAndRemoveHandlerImmediatelyWithSubscribe() throws Exception {
AtomicReference<Double> value = new AtomicReference<>(0.0); AtomicReference<Double> value = new AtomicReference<>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
Action action = () -> value.getAndUpdate((val) -> val + 1); Action action = () -> value.getAndUpdate((val) -> val + 1);
Subscription sub = hubConnection.on("inc", action); Subscription sub = hubConnection.on("inc", action);
@ -306,7 +305,7 @@ class HubConnectionTest {
public void registeringMultipleHandlersThatTakeParamsAndBothGetTriggered() throws Exception { public void registeringMultipleHandlersThatTakeParamsAndBothGetTriggered() throws Exception {
AtomicReference<Double> value = new AtomicReference<>(0.0); AtomicReference<Double> value = new AtomicReference<>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
Action1<Double> action = (number) -> value.getAndUpdate((val) -> val + number); Action1<Double> action = (number) -> value.getAndUpdate((val) -> val + number);
@ -325,7 +324,7 @@ class HubConnectionTest {
@Test @Test
public void invokeWaitsForCompletionMessage() throws Exception { public void invokeWaitsForCompletionMessage() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.start(); hubConnection.start();
mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR);
@ -342,7 +341,7 @@ class HubConnectionTest {
@Test @Test
public void multipleInvokesWaitForOwnCompletionMessage() throws Exception { public void multipleInvokesWaitForOwnCompletionMessage() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.start(); hubConnection.start();
mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR);
@ -365,7 +364,7 @@ class HubConnectionTest {
@Test @Test
public void invokeWorksForPrimitiveTypes() throws Exception { public void invokeWorksForPrimitiveTypes() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.start(); hubConnection.start();
mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR);
@ -383,7 +382,7 @@ class HubConnectionTest {
@Test @Test
public void completionMessageCanHaveError() throws Exception { public void completionMessageCanHaveError() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.start(); hubConnection.start();
mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR);
@ -407,7 +406,7 @@ class HubConnectionTest {
@Test @Test
public void stopCancelsActiveInvokes() throws Exception { public void stopCancelsActiveInvokes() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.start(); hubConnection.start();
mockTransport.receiveMessage("{}" + RECORD_SEPARATOR); mockTransport.receiveMessage("{}" + RECORD_SEPARATOR);
@ -432,7 +431,7 @@ class HubConnectionTest {
public void sendWithNoParamsTriggersOnHandler() throws Exception { public void sendWithNoParamsTriggersOnHandler() throws Exception {
AtomicReference<Integer> value = new AtomicReference<>(0); AtomicReference<Integer> value = new AtomicReference<>(0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", () ->{ hubConnection.on("inc", () ->{
assertEquals(Integer.valueOf(0), value.get()); assertEquals(Integer.valueOf(0), value.get());
@ -451,7 +450,7 @@ class HubConnectionTest {
public void sendWithParamTriggersOnHandler() throws Exception { public void sendWithParamTriggersOnHandler() throws Exception {
AtomicReference<String> value = new AtomicReference<>(); AtomicReference<String> value = new AtomicReference<>();
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param) ->{ hubConnection.on("inc", (param) ->{
assertNull(value.get()); assertNull(value.get());
@ -473,7 +472,7 @@ class HubConnectionTest {
AtomicReference<Double> value2 = new AtomicReference<>(); AtomicReference<Double> value2 = new AtomicReference<>();
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2) ->{ hubConnection.on("inc", (param1, param2) ->{
assertNull(value1.get()); assertNull(value1.get());
@ -500,7 +499,7 @@ class HubConnectionTest {
AtomicReference<String> value3 = new AtomicReference<>(); AtomicReference<String> value3 = new AtomicReference<>();
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2, param3) ->{ hubConnection.on("inc", (param1, param2, param3) ->{
assertNull(value1.get()); assertNull(value1.get());
@ -531,7 +530,7 @@ class HubConnectionTest {
AtomicReference<String> value4 = new AtomicReference<>(); AtomicReference<String> value4 = new AtomicReference<>();
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2, param3, param4) ->{ hubConnection.on("inc", (param1, param2, param3, param4) ->{
assertNull(value1.get()); assertNull(value1.get());
@ -565,7 +564,7 @@ class HubConnectionTest {
AtomicReference<Double> value5 = new AtomicReference<>(); AtomicReference<Double> value5 = new AtomicReference<>();
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2, param3, param4, param5) ->{ hubConnection.on("inc", (param1, param2, param3, param4, param5) ->{
assertNull(value1.get()); assertNull(value1.get());
@ -603,7 +602,7 @@ class HubConnectionTest {
AtomicReference<String> value6 = new AtomicReference<>(); AtomicReference<String> value6 = new AtomicReference<>();
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2, param3, param4, param5, param6) -> { hubConnection.on("inc", (param1, param2, param3, param4, param5, param6) -> {
assertNull(value1.get()); assertNull(value1.get());
@ -645,7 +644,7 @@ class HubConnectionTest {
AtomicReference<String> value7 = new AtomicReference<>(); AtomicReference<String> value7 = new AtomicReference<>();
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2, param3, param4, param5, param6, param7) -> { hubConnection.on("inc", (param1, param2, param3, param4, param5, param6, param7) -> {
assertNull(value1.get()); assertNull(value1.get());
@ -691,7 +690,7 @@ class HubConnectionTest {
AtomicReference<String> value8 = new AtomicReference<>(); AtomicReference<String> value8 = new AtomicReference<>();
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1, param2, param3, param4, param5, param6, param7, param8) -> { hubConnection.on("inc", (param1, param2, param3, param4, param5, param6, param7, param8) -> {
assertNull(value1.get()); assertNull(value1.get());
@ -738,7 +737,7 @@ class HubConnectionTest {
AtomicReference<Custom> value1 = new AtomicReference<>(); AtomicReference<Custom> value1 = new AtomicReference<>();
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", (param1) -> { hubConnection.on("inc", (param1) -> {
assertNull(value1.get()); assertNull(value1.get());
@ -763,7 +762,7 @@ class HubConnectionTest {
public void receiveHandshakeResponseAndMessage() throws Exception { public void receiveHandshakeResponseAndMessage() throws Exception {
AtomicReference<Double> value = new AtomicReference<Double>(0.0); AtomicReference<Double> value = new AtomicReference<Double>(0.0);
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("inc", () ->{ hubConnection.on("inc", () ->{
assertEquals(Double.valueOf(0), value.get()); assertEquals(Double.valueOf(0), value.get());
@ -784,8 +783,7 @@ class HubConnectionTest {
@Test @Test
public void onClosedCallbackRunsWhenStopIsCalled() throws Exception { public void onClosedCallbackRunsWhenStopIsCalled() throws Exception {
AtomicReference<String> value1 = new AtomicReference<>(); AtomicReference<String> value1 = new AtomicReference<>();
Transport mockTransport = new MockTransport(); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com");
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient());
hubConnection.start(); hubConnection.start();
hubConnection.onClosed((ex) -> { hubConnection.onClosed((ex) -> {
assertNull(value1.get()); assertNull(value1.get());
@ -801,8 +799,7 @@ class HubConnectionTest {
public void multipleOnClosedCallbacksRunWhenStopIsCalled() throws Exception { public void multipleOnClosedCallbacksRunWhenStopIsCalled() throws Exception {
AtomicReference<String> value1 = new AtomicReference<>(); AtomicReference<String> value1 = new AtomicReference<>();
AtomicReference<String> value2 = new AtomicReference<>(); AtomicReference<String> value2 = new AtomicReference<>();
Transport mockTransport = new MockTransport(); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com");
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient());
hubConnection.start(); hubConnection.start();
hubConnection.onClosed((ex) -> { hubConnection.onClosed((ex) -> {
@ -827,7 +824,7 @@ class HubConnectionTest {
@Test @Test
public void hubConnectionClosesAndRunsOnClosedCallbackAfterCloseMessageWithError() throws Exception { public void hubConnectionClosesAndRunsOnClosedCallbackAfterCloseMessageWithError() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.onClosed((ex) -> { hubConnection.onClosed((ex) -> {
assertEquals(ex.getMessage(), "There was an error"); assertEquals(ex.getMessage(), "There was an error");
}); });
@ -843,8 +840,7 @@ class HubConnectionTest {
@Test @Test
public void callingStartOnStartedHubConnectionNoOps() throws Exception { public void callingStartOnStartedHubConnectionNoOps() throws Exception {
Transport mockTransport = new MockTransport(); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com");
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient());
hubConnection.start(); hubConnection.start();
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
@ -857,8 +853,7 @@ class HubConnectionTest {
@Test @Test
public void cannotSendBeforeStart() throws Exception { public void cannotSendBeforeStart() throws Exception {
Transport mockTransport = new MockTransport(); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com");
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient());
assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState()); assertEquals(HubConnectionState.DISCONNECTED, hubConnection.getConnectionState());
Throwable exception = assertThrows(HubException.class, () -> hubConnection.send("inc")); Throwable exception = assertThrows(HubException.class, () -> hubConnection.send("inc"));
@ -868,7 +863,7 @@ class HubConnectionTest {
@Test @Test
public void errorWhenReceivingInvokeWithIncorrectArgumentLength() throws Exception { public void errorWhenReceivingInvokeWithIncorrectArgumentLength() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport mockTransport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HubConnection hubConnection = TestUtils.createHubConnection("http://example.com", mockTransport);
hubConnection.on("Send", (s) -> { hubConnection.on("Send", (s) -> {
assertTrue(false); assertTrue(false);
}, String.class); }, String.class);
@ -886,9 +881,10 @@ class HubConnectionTest {
TestHttpClient client = new TestHttpClient() TestHttpClient client = new TestHttpClient()
.on("POST", (req) -> CompletableFuture.completedFuture(new HttpResponse(404, "", ""))); .on("POST", (req) -> CompletableFuture.completedFuture(new HttpResponse(404, "", "")));
HttpConnectionOptions options = new HttpConnectionOptions();
options.setHttpClient(client);
HubConnection hubConnection = new HubConnectionBuilder() HubConnection hubConnection = new HubConnectionBuilder()
.withUrl("http://example.com") .withUrl("http://example.com", options)
.configureHttpClient(client)
.build(); .build();
try { try {
@ -905,8 +901,11 @@ class HubConnectionTest {
TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate", TestHttpClient client = new TestHttpClient().on("POST", "http://example.com/negotiate",
(req) -> CompletableFuture.completedFuture(new HttpResponse(200, "", "{\"url\":\"http://example.com\"}"))); (req) -> CompletableFuture.completedFuture(new HttpResponse(200, "", "{\"url\":\"http://example.com\"}")));
HubConnection hubConnection = new HubConnectionBuilder().withUrl("http://example.com") HttpConnectionOptions options = new HttpConnectionOptions();
.configureHttpClient(client).build(); options.setHttpClient(client);
HubConnection hubConnection = new HubConnectionBuilder()
.withUrl("http://example.com", options)
.build();
ExecutionException exception = assertThrows(ExecutionException.class, () -> hubConnection.start().get(1000, TimeUnit.MILLISECONDS)); ExecutionException exception = assertThrows(ExecutionException.class, () -> hubConnection.start().get(1000, TimeUnit.MILLISECONDS));
assertEquals("Negotiate redirection limit exceeded.", exception.getCause().getMessage()); assertEquals("Negotiate redirection limit exceeded.", exception.getCause().getMessage());
@ -922,8 +921,10 @@ class HubConnectionTest {
MockTransport transport = new MockTransport(); MockTransport transport = new MockTransport();
HttpConnectionOptions options = new HttpConnectionOptions(); HttpConnectionOptions options = new HttpConnectionOptions();
options.setTransport(transport); options.setTransport(transport);
HubConnection hubConnection = new HubConnectionBuilder().withUrl("http://example.com", options) options.setHttpClient(client);
.configureHttpClient(client).build(); HubConnection hubConnection = new HubConnectionBuilder()
.withUrl("http://example.com", options)
.build();
hubConnection.start().get(1000, TimeUnit.MILLISECONDS); hubConnection.start().get(1000, TimeUnit.MILLISECONDS);
@ -940,8 +941,10 @@ class HubConnectionTest {
MockTransport transport = new MockTransport(); MockTransport transport = new MockTransport();
HttpConnectionOptions options = new HttpConnectionOptions(); HttpConnectionOptions options = new HttpConnectionOptions();
options.setTransport(transport); options.setTransport(transport);
HubConnection hubConnection = new HubConnectionBuilder().withUrl("http://example.com", options) options.setHttpClient(client);
.configureHttpClient(client).build(); HubConnection hubConnection = new HubConnectionBuilder()
.withUrl("http://example.com", options)
.build();
ExecutionException exception = assertThrows(ExecutionException.class, () -> hubConnection.start().get(1000, TimeUnit.MILLISECONDS)); ExecutionException exception = assertThrows(ExecutionException.class, () -> hubConnection.start().get(1000, TimeUnit.MILLISECONDS));
assertEquals("Test error.", exception.getCause().getMessage()); assertEquals("Test error.", exception.getCause().getMessage());
@ -958,18 +961,75 @@ class HubConnectionTest {
MockTransport transport = new MockTransport(); MockTransport transport = new MockTransport();
HttpConnectionOptions options = new HttpConnectionOptions(); HttpConnectionOptions options = new HttpConnectionOptions();
options.setTransport(transport); options.setTransport(transport);
HubConnection hubConnection = new HubConnectionBuilder().withUrl("http://example.com", options) options.setHttpClient(client);
.configureHttpClient(client).build(); HubConnection hubConnection = new HubConnectionBuilder()
.withUrl("http://example.com", options)
.build();
hubConnection.start().get(1000, TimeUnit.MILLISECONDS); hubConnection.start().get(1000, TimeUnit.MILLISECONDS);
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
hubConnection.stop(); hubConnection.stop();
} }
@Test
public void accessTokenProviderIsUsedForNegotiate()
throws InterruptedException, ExecutionException, TimeoutException, Exception {
AtomicReference<String> token = new AtomicReference<>();
TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate",
(req) -> {
token.set(req.getHeaders().get("Authorization"));
return CompletableFuture
.completedFuture(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"));
});
MockTransport transport = new MockTransport();
HttpConnectionOptions options = new HttpConnectionOptions();
options.setTransport(transport);
options.setHttpClient(client);
options.setAccessTokenProvider(() -> CompletableFuture.completedFuture("secretToken"));
HubConnection hubConnection = new HubConnectionBuilder().withUrl("http://example.com", options).build();
hubConnection.start().get(1000, TimeUnit.MILLISECONDS);
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
hubConnection.stop();
assertEquals("Bearer secretToken", token.get());
}
@Test
public void accessTokenProviderIsOverriddenFromRedirectNegotiate()
throws InterruptedException, ExecutionException, TimeoutException, Exception {
AtomicReference<String> token = new AtomicReference<>();
TestHttpClient client = new TestHttpClient()
.on("POST", "http://example.com/negotiate", (req) -> CompletableFuture.completedFuture(new HttpResponse(200, "", "{\"url\":\"http://testexample.com/\",\"accessToken\":\"newToken\"}")))
.on("POST", "http://testexample.com/negotiate", (req) -> {
token.set(req.getHeaders().get("Authorization"));
return CompletableFuture
.completedFuture(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"));
});
MockTransport transport = new MockTransport();
HttpConnectionOptions options = new HttpConnectionOptions();
options.setTransport(transport);
options.setHttpClient(client);
options.setAccessTokenProvider(() -> CompletableFuture.completedFuture("secretToken"));
HubConnection hubConnection = new HubConnectionBuilder().withUrl("http://example.com", options).build();
hubConnection.start().get(1000, TimeUnit.MILLISECONDS);
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
hubConnection.stop();
assertEquals("Bearer newToken", token.get());
}
@Test @Test
public void hubConnectionCanBeStartedAfterBeingStopped() throws Exception { public void hubConnectionCanBeStartedAfterBeingStopped() throws Exception {
MockTransport mockTransport = new MockTransport(); MockTransport transport = new MockTransport();
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true, new TestHttpClient()); HttpConnectionOptions options = new HttpConnectionOptions();
options.setTransport(transport);
options.setSkipNegotiate(true);
HubConnection hubConnection = new HubConnectionBuilder().withUrl("http://example.com", options).build();
hubConnection.start().get(1000, TimeUnit.MILLISECONDS); hubConnection.start().get(1000, TimeUnit.MILLISECONDS);
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
@ -990,7 +1050,10 @@ class HubConnectionTest {
.on("POST", "http://testexample.com/negotiate", (req) -> CompletableFuture .on("POST", "http://testexample.com/negotiate", (req) -> CompletableFuture
.completedFuture(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\"" .completedFuture(new HttpResponse(200, "", "{\"connectionId\":\"bVOiRPG8-6YiJ6d7ZcTOVQ\",\""
+ "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}"))); + "availableTransports\":[{\"transport\":\"WebSockets\",\"transferFormats\":[\"Text\",\"Binary\"]}]}")));
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), false, client); HttpConnectionOptions options = new HttpConnectionOptions();
options.setTransport(mockTransport);
options.setHttpClient(client);
HubConnection hubConnection = new HubConnectionBuilder().withUrl("http://example.com", options).build();
hubConnection.start().get(1000, TimeUnit.MILLISECONDS); hubConnection.start().get(1000, TimeUnit.MILLISECONDS);
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState()); assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());

View File

@ -0,0 +1,24 @@
// 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.aspnet.signalr;
class TestUtils {
static HubConnection createHubConnection(String url) {
return createHubConnection(url, new MockTransport(), new NullLogger(), true, new TestHttpClient());
}
static HubConnection createHubConnection(String url, Transport transport) {
return createHubConnection(url, transport, new NullLogger(), true, new TestHttpClient());
}
static HubConnection createHubConnection(String url, Transport transport, Logger logger, boolean skipNegotiate, HttpClient client) {
HttpConnectionOptions options = new HttpConnectionOptions();
options.setTransport(transport);
options.setLogger(logger);
options.setSkipNegotiate(skipNegotiate);
options.setHttpClient(client);
HubConnectionBuilder builder = new HubConnectionBuilder();
return builder.withUrl(url, options).build();
}
}