コード例 #1
0
    public static TestHttpMessageHandler CreateDefault()
    {
        var testHttpMessageHandler = new TestHttpMessageHandler();

        var deleteCts = new CancellationTokenSource();

        testHttpMessageHandler.OnSocketSend((_, __) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted));
        testHttpMessageHandler.OnLongPoll(async cancellationToken =>
        {
            var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, deleteCts.Token);

            // Just block until canceled
            var tcs = new TaskCompletionSource();
            using (cts.Token.Register(() => tcs.TrySetResult()))
            {
                await tcs.Task;
            }
            return(ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
        });
        testHttpMessageHandler.OnRequest((request, next, cancellationToken) =>
        {
            if (request.Method.Equals(HttpMethod.Delete) && request.RequestUri.PathAndQuery.Contains("id="))
            {
                deleteCts.Cancel();
                return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.Accepted)));
            }

            return(next());
        });

        return(testHttpMessageHandler);
    }
コード例 #2
0
        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);
            Assert.Equal(1, callCount);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
    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
        {
            DefaultTransferFormat     = TransferFormat.Text,
            HttpMessageHandlerFactory = _ => testHandler,
        }),
            NullLoggerFactory.Instance);

        // We don't care about the specific exception
        await Assert.ThrowsAnyAsync <Exception>(async() => await factory.ConnectAsync(new UriEndPoint(new Uri("http://example.com"))));

        // We care that the handler (and by extension the client) was disposed
        Assert.True(testHandler.Disposed);
    }
コード例 #6
0
        public async Task HttpConnectionFailsAfterFirstRetryFailsServerSentEvents()
        {
            var testHttpHandler      = new TestHttpMessageHandler(autoNegotiate: false);
            var accessTokenCallCount = 0;

            testHttpHandler.OnNegotiate((_, cancellationToken) =>
            {
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent()));
            });

            testHttpHandler.OnSocketSend((_, _) =>
            {
                return(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized));
            });

            var tcs    = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var stream = new BlockingStream(tcs);

            testHttpHandler.OnRequest((request, next, token) =>
            {
                return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK, new StreamContent(stream))));
            });

            Task <string> AccessTokenProvider()
            {
                accessTokenCallCount++;
                return(Task.FromResult(accessTokenCallCount.ToString(CultureInfo.InvariantCulture)));
            }

            await WithConnectionAsync(
                CreateConnection(testHttpHandler, transportType : HttpTransportType.ServerSentEvents, accessTokenProvider : AccessTokenProvider),
                async (connection) =>
            {
                await connection.StartAsync().DefaultTimeout();
                await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello world 1"));
                await Assert.ThrowsAsync <HttpRequestException>(async() => await connection.Transport.Input.ReadAllAsync());
            });

            // 1 negotiate + 1 retry stream request
            Assert.Equal(2, accessTokenCallCount);
        }
コード例 #7
0
        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);
                });
            }
        }
コード例 #8
0
        public async Task HttpConnectionRetriesAccessTokenProviderWhenAuthFailsServerSentEvents()
        {
            var testHttpHandler      = new TestHttpMessageHandler(autoNegotiate: false);
            var requestsExecuted     = false;
            var accessTokenCallCount = 0;

            testHttpHandler.OnNegotiate((_, cancellationToken) =>
            {
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent()));
            });

            var sendRequestExecuted = false;
            var sendFinishedTcs     = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);

            testHttpHandler.OnSocketSend((_, _) =>
            {
                if (!sendRequestExecuted)
                {
                    sendRequestExecuted = true;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized));
                }
                sendFinishedTcs.SetResult();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });

            var tcs    = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var stream = new BlockingStream(tcs);

            testHttpHandler.OnRequest((request, next, token) =>
            {
                if (!requestsExecuted)
                {
                    requestsExecuted = true;
                    return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized)));
                }

                Assert.Equal("Bearer", request.Headers.Authorization.Scheme);

                Assert.Equal(accessTokenCallCount.ToString(CultureInfo.InvariantCulture), request.Headers.Authorization.Parameter);

                return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK, new StreamContent(stream))));
            });

            Task <string> AccessTokenProvider()
            {
                accessTokenCallCount++;
                return(Task.FromResult(accessTokenCallCount.ToString(CultureInfo.InvariantCulture)));
            }

            await WithConnectionAsync(
                CreateConnection(testHttpHandler, transportType : HttpTransportType.ServerSentEvents, accessTokenProvider : AccessTokenProvider),
                async (connection) =>
            {
                await connection.StartAsync().DefaultTimeout();
                await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello world 1"));
                await sendFinishedTcs.Task;
                tcs.TrySetResult();
                await connection.Transport.Input.ReadAllAsync();
            });

            // 1 negotiate + 1 retry stream request + 1 retry send
            Assert.Equal(3, accessTokenCallCount);
        }
コード例 #9
0
        public async Task HttpConnectionRetriesAccessTokenProviderWhenAuthFailsLongPolling()
        {
            var testHttpHandler      = new TestHttpMessageHandler(autoNegotiate: false);
            var requestsExecuted     = false;
            var accessTokenCallCount = 0;
            var pollCount            = 0;

            testHttpHandler.OnNegotiate((_, cancellationToken) =>
            {
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent()));
            });

            var startSendTcs     = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var longPollTcs      = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var messageFragments = new[] { "This ", "is ", "a ", "test" };

            testHttpHandler.OnLongPoll(async _ =>
            {
                // fail every other request
                if (pollCount % 2 == 0)
                {
                    pollCount++;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized));
                }
                if (pollCount / 2 >= messageFragments.Length)
                {
                    startSendTcs.SetResult();
                    await longPollTcs.Task;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
                }

                var resp = ResponseUtils.CreateResponse(HttpStatusCode.OK, messageFragments[pollCount / 2]);
                pollCount++;
                return(resp);
            });

            var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);

            testHttpHandler.OnRequest((request, next, token) =>
            {
                if (!requestsExecuted)
                {
                    requestsExecuted = true;
                    return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized)));
                }

                Assert.Equal("Bearer", request.Headers.Authorization.Scheme);

                Assert.Equal(accessTokenCallCount.ToString(CultureInfo.InvariantCulture), request.Headers.Authorization.Parameter);

                tcs.SetResult();

                return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK)));
            });

            Task <string> AccessTokenProvider()
            {
                accessTokenCallCount++;
                return(Task.FromResult(accessTokenCallCount.ToString(CultureInfo.InvariantCulture)));
            }

            await WithConnectionAsync(
                CreateConnection(testHttpHandler, transportType : HttpTransportType.LongPolling, accessTokenProvider : AccessTokenProvider),
                async (connection) =>
            {
                await connection.StartAsync().DefaultTimeout();
                var message = await connection.Transport.Input.ReadAtLeastAsync(14);
                Assert.Equal("This is a test", Encoding.UTF8.GetString(message.Buffer));
                await startSendTcs.Task;
                await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello world 1"));
                await tcs.Task;
                longPollTcs.SetResult();
            });

            // 1 negotiate + 4 (number of polls) + 1 for last poll + 1 for send
            Assert.Equal(7, accessTokenCallCount);
        }