public async Task ExceptionOnSendAsyncClosesWithError() { var testHttpHandler = new TestHttpMessageHandler(); var longPollTcs = new TaskCompletionSource <HttpResponseMessage>(TaskCreationOptions.RunContinuationsAsynchronously); testHttpHandler.OnLongPoll(cancellationToken => { cancellationToken.Register(() => longPollTcs.TrySetResult(null)); return(longPollTcs.Task); }); testHttpHandler.OnSocketSend((buf, cancellationToken) => { return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError))); }); await WithConnectionAsync( CreateConnection(testHttpHandler), async (connection, closed) => { await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.SendAsync(new byte[] { 0 }).OrTimeout(); var exception = await Assert.ThrowsAsync <HttpRequestException>(() => closed.OrTimeout()); }); }
public async Task CanSendData() { var data = new byte[] { 1, 1, 2, 3, 5, 8 }; var testHttpHandler = new TestHttpMessageHandler(); var sendTcs = new TaskCompletionSource <byte[]>(); var longPollTcs = new TaskCompletionSource <HttpResponseMessage>(); testHttpHandler.OnLongPoll(cancellationToken => longPollTcs.Task); testHttpHandler.OnSocketSend((buf, cancellationToken) => { sendTcs.TrySetResult(buf); return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.Accepted))); }); await WithConnectionAsync( CreateConnection(testHttpHandler), async (connection, closed) => { await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.SendAsync(data).OrTimeout(); Assert.Equal(data, await sendTcs.Task.OrTimeout()); longPollTcs.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); }); }
public async Task NegotiateThatReturnsUrlGetFollowed() { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); var firstNegotiate = true; testHttpHandler.OnNegotiate((request, cancellationToken) => { if (firstNegotiate) { firstNegotiate = false; return(ResponseUtils.CreateResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(new { url = "https://another.domain.url/chat" }))); } return(ResponseUtils.CreateResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(new { connectionId = "0rge0d00-0040-0030-0r00-000q00r00e00", availableTransports = new object[] { new { transport = "LongPolling", transferFormats = new[] { "Text" } }, } }))); }); testHttpHandler.OnLongPoll((token) => { var tcs = new TaskCompletionSource <HttpResponseMessage>(TaskCreationOptions.RunContinuationsAsynchronously); token.Register(() => tcs.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent))); return(tcs.Task); }); testHttpHandler.OnLongPollDelete((token) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted)); using (var noErrorScope = new VerifyNoErrorsScope()) { await WithConnectionAsync( CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory), async (connection) => { await connection.StartAsync().DefaultTimeout(); }); } Assert.Equal("http://fakeuri.org/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[0].RequestUri.ToString()); Assert.Equal("https://another.domain.url/chat/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[1].RequestUri.ToString()); Assert.Equal("https://another.domain.url/chat?id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[2].RequestUri.ToString()); Assert.Equal("https://another.domain.url/chat?id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[3].RequestUri.ToString()); Assert.Equal(5, testHttpHandler.ReceivedRequests.Count); }
private static HttpConnection CreateConnection(HttpMessageHandler httpHandler = null, ILoggerFactory loggerFactory = null, string url = null, ITransport transport = null, ITransportFactory transportFactory = null, HttpTransportType transportType = HttpTransportType.LongPolling) { var httpOptions = new HttpOptions() { HttpMessageHandler = (httpMessageHandler) => httpHandler ?? TestHttpMessageHandler.CreateDefault(), }; return(CreateConnection(httpOptions, loggerFactory, url, transport, transportFactory, transportType)); }
private static HttpConnection CreateConnection(HttpMessageHandler httpHandler = null, ILoggerFactory loggerFactory = null, string url = null, ITransport transport = null) { loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; var httpOptions = new HttpOptions() { HttpMessageHandler = httpHandler ?? TestHttpMessageHandler.CreateDefault(), }; var uri = new Uri(url ?? "http://fakeuri.org/"); var connection = (transport != null) ? new HttpConnection(uri, new TestTransportFactory(transport), loggerFactory, httpOptions) : new HttpConnection(uri, TransportType.LongPolling, loggerFactory, httpOptions); return(connection); }
private async Task RunInvalidNegotiateResponseTest <TException>(string negotiatePayload, string expectedExceptionMessage) where TException : Exception { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); testHttpHandler.OnNegotiate((_, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.OK, negotiatePayload)); await WithConnectionAsync( CreateConnection(testHttpHandler), async (connection) => { var exception = await Assert.ThrowsAsync <TException>( () => connection.StartAsync().DefaultTimeout()); Assert.Equal(expectedExceptionMessage, exception.Message); }); }
public async Task HttpOptionsSetOntoHttpClientHandler() { var testHttpHandler = TestHttpMessageHandler.CreateDefault(); var negotiateUrlTcs = new TaskCompletionSource <string>(); testHttpHandler.OnNegotiate((request, cancellationToken) => { negotiateUrlTcs.TrySetResult(request.RequestUri.ToString()); return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent())); }); HttpClientHandler httpClientHandler = null; var httpOptions = new HttpConnectionOptions(); httpOptions.Url = new Uri("http://fakeuri.org/"); httpOptions.HttpMessageHandlerFactory = inner => { httpClientHandler = (HttpClientHandler)inner; return(testHttpHandler); }; httpOptions.Cookies.Add(new Cookie("Name", "Value", string.Empty, "fakeuri.org")); var clientCertificate = new X509Certificate(Array.Empty <byte>()); httpOptions.ClientCertificates.Add(clientCertificate); httpOptions.UseDefaultCredentials = false; httpOptions.Credentials = Mock.Of <ICredentials>(); httpOptions.Proxy = Mock.Of <IWebProxy>(); httpOptions.Transports = HttpTransportType.LongPolling; await WithConnectionAsync( CreateConnection(httpOptions), async (connection) => { await connection.StartAsync().DefaultTimeout(); }); Assert.NotNull(httpClientHandler); Assert.Equal(1, httpClientHandler.CookieContainer.Count); Assert.Single(httpClientHandler.ClientCertificates); Assert.Same(clientCertificate, httpClientHandler.ClientCertificates[0]); Assert.False(httpClientHandler.UseDefaultCredentials); Assert.Same(httpOptions.Proxy, httpClientHandler.Proxy); Assert.Same(httpOptions.Credentials, httpClientHandler.Credentials); }
public async Task StartSkipsOverTransportsThatTheClientDoesNotUnderstand() { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); testHttpHandler.OnLongPoll(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); testHttpHandler.OnNegotiate((request, cancellationToken) => { return(ResponseUtils.CreateResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(new { connectionId = "00000000-0000-0000-0000-000000000000", availableTransports = new object[] { new { transport = "QuantumEntanglement", transferFormats = new[] { "Qbits" }, }, new { transport = "CarrierPigeon", transferFormats = new[] { "Text" }, }, new { transport = "LongPolling", transferFormats = new[] { "Text", "Binary" } }, } }))); }); var transportFactory = new Mock <ITransportFactory>(MockBehavior.Strict); transportFactory.Setup(t => t.CreateTransport(HttpTransportType.LongPolling)) .Returns(new TestTransport(transferFormat: TransferFormat.Text | TransferFormat.Binary)); using (var noErrorScope = new VerifyNoErrorsScope()) { await WithConnectionAsync( CreateConnection(testHttpHandler, transportFactory : transportFactory.Object, loggerFactory : noErrorScope.LoggerFactory, transferFormat : TransferFormat.Binary), async (connection) => { await connection.StartAsync().DefaultTimeout(); }); } }
public async Task HttpConnectionSetsUserAgentOnAllRequests(HttpTransportType transportType) { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); var requestsExecuted = false; testHttpHandler.OnNegotiate((_, cancellationToken) => { return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent())); }); testHttpHandler.OnRequest(async(request, next, token) => { var userAgentHeader = request.Headers.UserAgent.ToString(); Assert.NotNull(userAgentHeader); Assert.StartsWith("Microsoft SignalR/", userAgentHeader); // user agent version should come from version embedded in assembly metadata var assemblyVersion = typeof(Constants) .Assembly .GetCustomAttribute <AssemblyInformationalVersionAttribute>(); Assert.Contains(assemblyVersion.InformationalVersion, userAgentHeader); requestsExecuted = true; return(await next()); }); testHttpHandler.OnRequest((request, next, token) => { return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent))); }); await WithConnectionAsync( CreateConnection(testHttpHandler, transportType : transportType), async (connection) => { await connection.StartAsync().DefaultTimeout(); await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello World")); }); // Fail safe in case the code is modified and some requests don't execute as a result Assert.True(requestsExecuted); }
public async Task SendsDeleteRequestWhenTransportCompleted() { var handler = TestHttpMessageHandler.CreateDefault(); using (var httpClient = new HttpClient(handler)) { var longPollingTransport = new LongPollingTransport(httpClient); await longPollingTransport.StartAsync(TestUri, TransferFormat.Binary); await longPollingTransport.StopAsync(); var deleteRequest = handler.ReceivedRequests.SingleOrDefault(r => r.Method == HttpMethod.Delete); Assert.NotNull(deleteRequest); Assert.Equal(TestUri, deleteRequest.RequestUri); } }
public async Task HttpConnectionSetsAccessTokenOnAllRequests(HttpTransportType transportType) { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); var requestsExecuted = false; var callCount = 0; testHttpHandler.OnNegotiate((_, cancellationToken) => { return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent())); }); testHttpHandler.OnRequest(async(request, next, token) => { Assert.Equal("Bearer", request.Headers.Authorization.Scheme); // Call count increments with each call and is used as the access token Assert.Equal(callCount.ToString(CultureInfo.InvariantCulture), request.Headers.Authorization.Parameter); requestsExecuted = true; return(await next()); }); testHttpHandler.OnRequest((request, next, token) => { return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent))); }); Task <string> AccessTokenProvider() { callCount++; return(Task.FromResult(callCount.ToString(CultureInfo.InvariantCulture))); } await WithConnectionAsync( CreateConnection(testHttpHandler, transportType : transportType, accessTokenProvider : AccessTokenProvider), async (connection) => { await connection.StartAsync().DefaultTimeout(); await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello world 1")); await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello world 2")); }); // Fail safe in case the code is modified and some requests don't execute as a result Assert.True(requestsExecuted); }
public static HttpMessageHandler CreateDefault() { var testHttpMessageHandler = new TestHttpMessageHandler(); testHttpMessageHandler.OnSocketSend((_, __) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted)); testHttpMessageHandler.OnLongPoll(async cancellationToken => { // Just block until canceled var tcs = new TaskCompletionSource <object>(); using (cancellationToken.Register(() => tcs.TrySetResult(null))) { await tcs.Task; } return(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); }); return(testHttpMessageHandler); }
public async Task ConnectionIsDisposedIfItFailsToStartAsync() { var testHandler = new TestHttpMessageHandler(autoNegotiate: false, handleFirstPoll: false); testHandler.OnRequest((req, next, ct) => Task.FromException <HttpResponseMessage>(new Exception("BOOM"))); var factory = new HttpConnectionFactory(Options.Create(new HttpConnectionOptions() { Url = new Uri("http://example.com"), HttpMessageHandlerFactory = _ => testHandler }), NullLoggerFactory.Instance); // We don't care about the specific exception await Assert.ThrowsAnyAsync <Exception>(() => factory.ConnectAsync(TransferFormat.Text)); // We care that the handler (and by extension the client) was disposed Assert.True(testHandler.Disposed); }
public async Task StartSkipsOverTransportsThatDoNotSupportTheRequredTransferFormat() { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); testHttpHandler.OnLongPoll(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); testHttpHandler.OnNegotiate((request, cancellationToken) => { return(ResponseUtils.CreateResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(new { connectionId = "00000000-0000-0000-0000-000000000000", availableTransports = new object[] { new { transport = "WebSockets", transferFormats = new[] { "Qbits" }, }, new { transport = "ServerSentEvents", transferFormats = new[] { "Text" }, }, new { transport = "LongPolling", transferFormats = new[] { "Text", "Binary" } }, } }))); }); var transportFactory = new Mock <ITransportFactory>(MockBehavior.Strict); transportFactory.Setup(t => t.CreateTransport(HttpTransportType.LongPolling)) .Returns(new TestTransport(transferFormat: TransferFormat.Text | TransferFormat.Binary)); await WithConnectionAsync( CreateConnection(testHttpHandler, transportFactory : transportFactory.Object, transferFormat : TransferFormat.Binary), async (connection) => { await connection.StartAsync().DefaultTimeout(); }); }
public async Task CanCancelStartingConnectionAfterNegotiate() { using (StartVerifiableLog()) { // Set up a SyncPoint within Negotiate, so we can verify // that the call has gotten that far var negotiateSyncPoint = new SyncPoint(); var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); testHttpHandler.OnNegotiate(async(request, cancellationToken) => { // Wait here for the test code to cancel the "outer" token await negotiateSyncPoint.WaitToContinue().OrTimeout(); // Cancel cancellationToken.ThrowIfCancellationRequested(); return(ResponseUtils.CreateResponse(HttpStatusCode.OK)); }); await WithConnectionAsync( CreateConnection(testHttpHandler), async (connection) => { // Kick off StartAsync, but don't wait for it var cts = new CancellationTokenSource(); var startTask = connection.StartAsync(cts.Token); // Wait for the connection to get to the "WaitToContinue" call above, // which means it has gotten to Negotiate await negotiateSyncPoint.WaitForSyncPoint().OrTimeout(); // Assert that StartAsync has not yet been canceled Assert.False(startTask.IsCanceled); // Cancel StartAsync, then "release" the SyncPoint // so the negotiate handler can keep going cts.Cancel(); negotiateSyncPoint.Continue(); // Assert that StartAsync was canceled await Assert.ThrowsAsync <OperationCanceledException>(() => startTask).OrTimeout(); }); } }
public async Task SSEWontStartIfSuccessfulConnectionIsNotEstablished() { // TODO: Add logging https://github.com/aspnet/SignalR/issues/2879 var httpHandler = new TestHttpMessageHandler(); httpHandler.OnGet("/?id=00000000-0000-0000-0000-000000000000", (_, __) => { return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError))); }); var sse = new ServerSentEventsTransport(new HttpClient(httpHandler)); await WithConnectionAsync( CreateConnection(httpHandler, transport : sse), async (connection) => { await Assert.ThrowsAsync <InvalidOperationException>( () => connection.StartAsync(TransferFormat.Text).OrTimeout()); }); }
public async Task HttpRequestAndErrorResponseLogged() { var testHttpHandler = new TestHttpMessageHandler(false); testHttpHandler.OnNegotiate((request, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.BadGateway)); var httpOptions = new HttpConnectionOptions(); httpOptions.Url = new Uri("http://fakeuri.org/"); httpOptions.HttpMessageHandlerFactory = inner => testHttpHandler; const string loggerName = "Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler"; var testSink = new TestSink(); var logger = new TestLogger(loggerName, testSink, true); var mockLoggerFactory = new Mock <ILoggerFactory>(); mockLoggerFactory .Setup(m => m.CreateLogger(It.IsAny <string>())) .Returns((string categoryName) => (categoryName == loggerName) ? (ILogger)logger : NullLogger.Instance); try { await WithConnectionAsync( CreateConnection(httpOptions, loggerFactory : mockLoggerFactory.Object), async (connection) => { await connection.StartAsync().DefaultTimeout(); }); } catch { // ignore connection error } var writeList = testSink.Writes.ToList(); Assert.Equal(2, writeList.Count); Assert.Equal("SendingHttpRequest", writeList[0].EventId.Name); Assert.Equal("UnsuccessfulHttpResponse", writeList[1].EventId.Name); }
public async Task TransportPipeIsCompletedWhenErrorOccursInTransport() { bool ExpectedErrors(WriteContext writeContext) { return(writeContext.LoggerName == typeof(LongPollingTransport).FullName && writeContext.EventId.Name == "ErrorSending"); } using (StartVerifiableLog(expectedErrorsFilter: ExpectedErrors)) { var httpHandler = new TestHttpMessageHandler(); var longPollResult = new TaskCompletionSource <HttpResponseMessage>(); httpHandler.OnLongPoll(cancellationToken => { cancellationToken.Register(() => { longPollResult.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); }); return(longPollResult.Task); }); httpHandler.OnLongPollDelete(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); httpHandler.OnSocketSend((data, _) => { Assert.Collection(data, i => Assert.Equal(0x42, i)); return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError))); }); await WithConnectionAsync( CreateConnection(httpHandler, LoggerFactory), async (connection) => { await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.Transport.Output.WriteAsync(new byte[] { 0x42 }).OrTimeout(); // We should get the exception in the transport input completion. await Assert.ThrowsAsync <HttpRequestException>(() => connection.Transport.Input.WaitForWriterToComplete()); }); } }
public async Task CanceledCancellationTokenPassedToStartThrows() { using (StartVerifiableLog()) { bool transportStartCalled = false; var httpHandler = new TestHttpMessageHandler(); await WithConnectionAsync( CreateConnection(httpHandler, transport : new TestTransport(onTransportStart : () => { transportStartCalled = true; return(Task.CompletedTask); })), async (connection) => { await Assert.ThrowsAsync <TaskCanceledException>(async() => await connection.StartAsync(new CancellationToken(canceled: true))).OrTimeout(); }); Assert.False(transportStartCalled); } }
public async Task ConnectionIdGetsSetWithNegotiateProtocolGreaterThanZero() { string connectionId = null; var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); testHttpHandler.OnNegotiate((request, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(new { connectionId = "0rge0d00-0040-0030-0r00-000q00r00e00", negotiateVersion = 1, connectionToken = "different-id", availableTransports = new object[] { new { transport = "LongPolling", transferFormats = new[] { "Text" } }, }, newField = "ignore this", }))); testHttpHandler.OnLongPoll(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); testHttpHandler.OnLongPollDelete((token) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted)); using (var noErrorScope = new VerifyNoErrorsScope()) { await WithConnectionAsync( CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory), async (connection) => { await connection.StartAsync().DefaultTimeout(); connectionId = connection.ConnectionId; }); } Assert.Equal("0rge0d00-0040-0030-0r00-000q00r00e00", connectionId); Assert.Equal("http://fakeuri.org/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[0].RequestUri.ToString()); Assert.Equal("http://fakeuri.org/?id=different-id", testHttpHandler.ReceivedRequests[1].RequestUri.ToString()); }
public async Task TransportIsStoppedWhenConnectionIsDisposed() { var testHttpHandler = new TestHttpMessageHandler(); using (var httpClient = new HttpClient(testHttpHandler)) { var testTransport = new TestTransport(); await WithConnectionAsync( CreateConnection(transport : testTransport), async (connection) => { // Start the transport await connection.StartAsync(TransferFormat.Text).OrTimeout(); Assert.NotNull(testTransport.Receiving); Assert.False(testTransport.Receiving.IsCompleted); // Stop the connection, and we should stop the transport await connection.DisposeAsync().OrTimeout(); await testTransport.Receiving.OrTimeout(); }); } }
public async Task SSEWontStartIfSuccessfulConnectionIsNotEstablished() { using (StartLog(out var loggerFactory)) { var httpHandler = new TestHttpMessageHandler(); httpHandler.OnGet("/?id=00000000-0000-0000-0000-000000000000", (_, __) => { return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError))); }); var sse = new ServerSentEventsTransport(new HttpClient(httpHandler)); await WithConnectionAsync( CreateConnection(httpHandler, loggerFactory : loggerFactory, url : null, transport : sse), async (connection) => { await Assert.ThrowsAsync <InvalidOperationException>( () => connection.StartAsync(TransferFormat.Text).OrTimeout()); }); } }
public async Task HttpConnectionSetsInherentKeepAliveFeature(HttpTransportType transportType, bool expectedValue) { using (StartVerifiableLog()) { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); testHttpHandler.OnNegotiate((_, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent())); testHttpHandler.OnRequest((request, next, token) => Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent))); await WithConnectionAsync( CreateConnection(testHttpHandler, transportType : transportType, loggerFactory : LoggerFactory), async (connection) => { await connection.StartAsync().DefaultTimeout(); var feature = connection.Features.Get <IConnectionInherentKeepAliveFeature>(); Assert.NotNull(feature); Assert.Equal(expectedValue, feature.HasInherentKeepAlive); }); } }
private static HttpConnection CreateConnection( HttpMessageHandler httpHandler = null, ILoggerFactory loggerFactory = null, string url = null, ITransport transport = null, ITransportFactory transportFactory = null, HttpTransportType?transportType = null, Func <Task <string> > accessTokenFactory = null) { var httpOptions = new HttpConnectionOptions { Transports = transportType ?? HttpTransportType.LongPolling, HttpMessageHandlerFactory = (httpMessageHandler) => httpHandler ?? TestHttpMessageHandler.CreateDefault(), AccessTokenFactory = accessTokenFactory, }; if (url != null) { httpOptions.Url = new Uri(url); } return(CreateConnection(httpOptions, loggerFactory, transport, transportFactory)); }
public async Task CanReceiveData() { var testHttpHandler = new TestHttpMessageHandler(); testHttpHandler.OnLongPoll(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.OK, "42")); testHttpHandler.OnSocketSend((_, __) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted)); await WithConnectionAsync( CreateConnection(testHttpHandler), async (connection, closed) => { var receiveTcs = new TaskCompletionSource <string>(); connection.OnReceived((data, state) => { var tcs = ((TaskCompletionSource <string>)state); tcs.TrySetResult(Encoding.UTF8.GetString(data)); return(Task.CompletedTask); }, receiveTcs); await connection.StartAsync(TransferFormat.Text).OrTimeout(); Assert.Contains("42", await receiveTcs.Task.OrTimeout()); }); }
public async Task CorrectlyHandlesQueryStringWhenAppendingNegotiateToUrl(string requestedUrl, string expectedNegotiate) { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); var negotiateUrlTcs = new TaskCompletionSource <string>(); testHttpHandler.OnLongPoll(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); testHttpHandler.OnNegotiate((request, cancellationToken) => { negotiateUrlTcs.TrySetResult(request.RequestUri.ToString()); return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent())); }); await WithConnectionAsync( CreateConnection(testHttpHandler, url : requestedUrl), async (connection, closed) => { await connection.StartAsync(TransferFormat.Text).OrTimeout(); }); Assert.Equal(expectedNegotiate, await negotiateUrlTcs.Task.OrTimeout()); }
public async Task HttpConnectionSetsRequestedWithOnAllRequests(HttpTransportType transportType) { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); var requestsExecuted = false; testHttpHandler.OnNegotiate((_, cancellationToken) => { return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent())); }); testHttpHandler.OnRequest(async(request, next, token) => { var requestedWithHeader = request.Headers.GetValues(HeaderNames.XRequestedWith); var requestedWithValue = Assert.Single(requestedWithHeader); Assert.Equal("XMLHttpRequest", requestedWithValue); requestsExecuted = true; return(await next()); }); testHttpHandler.OnRequest((request, next, token) => { return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent))); }); await WithConnectionAsync( CreateConnection(testHttpHandler, transportType : transportType), async (connection) => { await connection.StartAsync().DefaultTimeout(); await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello World")); }); // Fail safe in case the code is modified and some requests don't execute as a result Assert.True(requestsExecuted); }
public async Task CanStartConnectionAfterConnectionStoppedWithError() { using (StartLog(out var loggerFactory)) { var httpHandler = new TestHttpMessageHandler(); var longPollResult = new TaskCompletionSource <HttpResponseMessage>(); httpHandler.OnLongPoll(cancellationToken => { cancellationToken.Register(() => { longPollResult.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); }); return(longPollResult.Task); }); httpHandler.OnSocketSend((data, _) => { Assert.Collection(data, i => Assert.Equal(0x42, i)); return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError))); }); await WithConnectionAsync( CreateConnection(httpHandler, loggerFactory), async (connection, closed) => { await connection.StartAsync(TransferFormat.Text).OrTimeout(); await connection.SendAsync(new byte[] { 0x42 }).OrTimeout(); // Wait for the connection to close, because the send failed. await Assert.ThrowsAsync <HttpRequestException>(() => closed.OrTimeout()); // Start it up again await connection.StartAsync(TransferFormat.Text).OrTimeout(); }); } }
public async Task NegotiateThatReturnsRedirectUrlForeverThrowsAfter100Tries() { var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); testHttpHandler.OnNegotiate((request, cancellationToken) => { return(ResponseUtils.CreateResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(new { url = "https://another.domain.url/chat" }))); }); using (var noErrorScope = new VerifyNoErrorsScope()) { await WithConnectionAsync( CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory), async (connection) => { var exception = await Assert.ThrowsAsync <InvalidOperationException>(() => connection.StartAsync().DefaultTimeout()); Assert.Equal("Negotiate redirection limit exceeded.", exception.Message); }); } }
public async Task NegotiateCanHaveNewFields() { string connectionId = null; var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false); testHttpHandler.OnNegotiate((request, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.OK, JsonConvert.SerializeObject(new { connectionId = "0rge0d00-0040-0030-0r00-000q00r00e00", availableTransports = new object[] { new { transport = "LongPolling", transferFormats = new[] { "Text" } }, }, newField = "ignore this", }))); testHttpHandler.OnLongPoll(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent)); testHttpHandler.OnLongPollDelete((token) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted)); using (var noErrorScope = new VerifyNoErrorsScope()) { await WithConnectionAsync( CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory), async (connection) => { await connection.StartAsync().DefaultTimeout(); connectionId = connection.ConnectionId; }); } Assert.Equal("0rge0d00-0040-0030-0r00-000q00r00e00", connectionId); }