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);
                });
            }
Esempio n. 7
0
        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);
            }
Esempio n. 10
0
        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);
            }
Esempio n. 12
0
        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());
                });
            }
Esempio n. 17
0
        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();
                    });
                }
            }
Esempio n. 22
0
            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);
                    });
                }
            }
Esempio n. 24
0
        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));
        }
Esempio n. 25
0
            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);
            }