Example #1
0
        public async Task AddsDFSHeaderWhenSendingARequest()
        {
            //Arrange
            var requestUrl          = $"https://someurl.com";
            var httpContextAccessor = A.Fake <IHttpContextAccessor>();

            httpContextAccessor.HttpContext = new DefaultHttpContext();
            var headerName   = "X-Dfc-Composite-Request";
            var headerValue1 = requestUrl;

            httpContextAccessor.HttpContext.Request.Headers.Add(headerName, headerValue1);

            var httpRequestChildMessage = new HttpRequestMessage(HttpMethod.Get, requestUrl);

            using (var handler = new CompositeRequestDelegatingHandler())
            {
                handler.InnerHandler = new StatusOkDelegatingHandler();

                //Act
                var invoker = new HttpMessageInvoker(handler);
                await invoker.SendAsync(httpRequestChildMessage, CancellationToken.None);

                //Assert
                Assert.Single(httpRequestChildMessage.Headers);
                Assert.True(httpRequestChildMessage.Headers.Contains(headerName));
                httpRequestChildMessage.Dispose();
                invoker.Dispose();
            }
        }
Example #2
0
 public void Dispose()
 {
     if (_shouldDicpose && !HttpClientProvider.IsCached(_client))
     {
         _client.Dispose();
     }
 }
 protected virtual void Dispose(bool disposing)
 {
     if (!_disposed)
     {
         _disposed = true;
         _messageInvoker.Dispose();
     }
 }
 private void OnAppDisposing()
 {
     if (!_disposed)
     {
         _messageInvoker.Dispose();
         _disposed = true;
     }
 }
 public void Cleanup()
 {
     _invoker.Dispose();
     _handler.Dispose();
     _listener.Dispose();
     _serverTask.GetAwaiter().GetResult();
     _serverCert.Dispose();
 }
Example #6
0
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _client.Dispose();
            }

            base.Dispose(disposing);
        }
Example #7
0
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _httpMessageInvoker.Dispose();
                _tokenClient.Dispose();
            }

            base.Dispose(disposing);
        }
        public void Dispose_DontDisposeHandler_HandlerNotDisposed()
        {
            var handler = new MockHandler();
            var invoker = new HttpMessageInvoker(handler, false);

            invoker.Dispose();
            Assert.Equal(0, handler.DisposeCount);

            Assert.Throws <ObjectDisposedException>(() => { Task t = invoker.SendAsync(new HttpRequestMessage(), CancellationToken.None); });
            Assert.Equal(0, handler.SendAsyncCount);
        }
        public void Dispose_DontDisposeHandler_HandlerNotDisposed()
        {
            var handler = new MockHandler();
            var invoker = new HttpMessageInvoker(handler, false);

            invoker.Dispose();
            Assert.Equal(0, handler.DisposeCount);

            Assert.Throws<ObjectDisposedException>(() => { Task t = invoker.SendAsync(new HttpRequestMessage(), CancellationToken.None); });
            Assert.Equal(0, handler.SendAsyncCount);
        }
Example #10
0
        public async Task WhenShellAuthenticatedPassOnToken()
        {
            //Arrange
            var path1      = "path1";
            var path2      = "path2";
            var requestUrl = $"https://someurl.com/{path1}";

            //Create fakes
            pathLocator         = A.Fake <IPathLocator>();
            httpContextAccessor = A.Fake <IHttpContextAccessor>();
            compositeDataProtectionDataProvider = A.Fake <ICompositeDataProtectionDataProvider>();

            //Fake calls
            A.CallTo(() => pathLocator.GetPath()).Returns(path1);
            A.CallTo(() => compositeDataProtectionDataProvider.Unprotect(A <string> .Ignored)).ReturnsLazily(x => x.Arguments.First().ToString());
            A.CallTo(() => compositeDataProtectionDataProvider.Protect(A <string> .Ignored)).ReturnsLazily(x => x.Arguments.First().ToString());

            //Set some headers on the incoming request
            httpContextAccessor.HttpContext = new DefaultHttpContext {
                User = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim> {
                    new Claim("bearer", "test")
                }, "mock"))
            };
            httpContextAccessor.HttpContext.Request.Headers.Add(HeaderNames.Cookie, $"{Constants.DfcSession}=sessionId1;{path1}v1=value1;{path1}v2=value2;{path2}v3=value3;{path2}v4=value4");
            httpContextAccessor.HttpContext.Session = new MockHttpSession();

            //Create a get request that is used to send data to the child app
            var httpRequestChildMessage = new HttpRequestMessage(HttpMethod.Get, requestUrl);

            //Create handlers and set the inner handler
            handler = new CookieDelegatingHandler(httpContextAccessor, pathLocator, compositeDataProtectionDataProvider)
            {
                InnerHandler = new StatusOkDelegatingHandler(),
            };

            //Act
            var invoker = new HttpMessageInvoker(handler);
            await invoker.SendAsync(httpRequestChildMessage, CancellationToken.None).ConfigureAwait(false);

            //Check that the values that are sent back are correct
            var headerValue = httpRequestChildMessage.Headers.Authorization;

            Assert.Equal("test", headerValue.Parameter);
            httpRequestChildMessage.Dispose();
            invoker.Dispose();
        }
Example #11
0
        public async Task CanCopyHeadersFromShellToChildApp()
        {
            //Arrange
            var path1      = "path1";
            var path2      = "path2";
            var requestUrl = $"https://someurl.com/{path1}";

            //Create fakes
            pathLocator         = A.Fake <IPathLocator>();
            httpContextAccessor = A.Fake <IHttpContextAccessor>();
            compositeDataProtectionDataProvider = A.Fake <ICompositeDataProtectionDataProvider>();

            //Fake calls
            A.CallTo(() => pathLocator.GetPath()).Returns(path1);
            A.CallTo(() => compositeDataProtectionDataProvider.Unprotect(A <string> .Ignored)).ReturnsLazily(x => x.Arguments.First().ToString());
            A.CallTo(() => compositeDataProtectionDataProvider.Protect(A <string> .Ignored)).ReturnsLazily(x => x.Arguments.First().ToString());

            //Set some headers on the incoming request
            httpContextAccessor.HttpContext = new DefaultHttpContext();
            httpContextAccessor.HttpContext.Request.Headers.Add(HeaderNames.Cookie, $"{path1}v1=value1;{path1}v2=value2;{path2}v3=value3;{path2}v4=value4");

            //Create a get request that is used to send data to the child app
            var httpRequestChildMessage = new HttpRequestMessage(HttpMethod.Get, requestUrl);

            //Create handlers and set the inner handler
            handler = new CookieDelegatingHandler(httpContextAccessor, pathLocator, compositeDataProtectionDataProvider)
            {
                InnerHandler = new StatusOkDelegatingHandler(),
            };

            //Act
            var invoker = new HttpMessageInvoker(handler);
            await invoker.SendAsync(httpRequestChildMessage, CancellationToken.None).ConfigureAwait(false);

            //Check that the child app has the correct number of headers based on the incoming request
            Assert.Single(httpRequestChildMessage.Headers);

            //Check that the values that are sent back are correct
            var headerValue = httpRequestChildMessage.Headers.First().Value.ToList();

            Assert.Equal("v1=value1", headerValue.First());
            Assert.Equal("v2=value2", headerValue.Last());
            httpRequestChildMessage.Dispose();
            invoker.Dispose();
        }
        public async Task ConnectAsync(Uri uri, HttpMessageInvoker?invoker, CancellationToken cancellationToken, ClientWebSocketOptions options)
        {
            bool disposeHandler = false;

            invoker ??= new HttpMessageInvoker(SetupHandler(options, out disposeHandler));
            HttpResponseMessage?response = null;

            bool disposeResponse = false;

            bool tryDowngrade = false;

            try
            {
                while (true)
                {
                    try
                    {
                        HttpRequestMessage request;
                        if (!tryDowngrade && options.HttpVersion >= HttpVersion.Version20 ||
                            (options.HttpVersion == HttpVersion.Version11 && options.HttpVersionPolicy == HttpVersionPolicy.RequestVersionOrHigher))
                        {
                            if (options.HttpVersion > HttpVersion.Version20 && options.HttpVersionPolicy != HttpVersionPolicy.RequestVersionOrLower)
                            {
                                throw new WebSocketException(WebSocketError.UnsupportedProtocol);
                            }
                            request = new HttpRequestMessage(HttpMethod.Connect, uri)
                            {
                                Version = HttpVersion.Version20
                            };
                            tryDowngrade = true;
                        }
                        else if (tryDowngrade || options.HttpVersion == HttpVersion.Version11)
                        {
                            request = new HttpRequestMessage(HttpMethod.Get, uri)
                            {
                                Version = HttpVersion.Version11
                            };
                            tryDowngrade = false;
                        }
                        else
                        {
                            throw new WebSocketException(WebSocketError.UnsupportedProtocol);
                        }

                        if (options._requestHeaders?.Count > 0) // use field to avoid lazily initializing the collection
                        {
                            foreach (string key in options.RequestHeaders)
                            {
                                request.Headers.TryAddWithoutValidation(key, options.RequestHeaders[key]);
                            }
                        }

                        string?secValue = AddWebSocketHeaders(request, options);

                        // Issue the request.
                        CancellationTokenSource?linkedCancellation;
                        CancellationTokenSource externalAndAbortCancellation;
                        if (cancellationToken.CanBeCanceled) // avoid allocating linked source if external token is not cancelable
                        {
                            linkedCancellation =
                                externalAndAbortCancellation =
                                    CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _abortSource.Token);
                        }
                        else
                        {
                            linkedCancellation           = null;
                            externalAndAbortCancellation = _abortSource;
                        }

                        using (linkedCancellation)
                        {
                            response = await invoker.SendAsync(request, externalAndAbortCancellation.Token).ConfigureAwait(false);

                            externalAndAbortCancellation.Token.ThrowIfCancellationRequested(); // poll in case sends/receives in request/response didn't observe cancellation
                        }

                        ValidateResponse(response, secValue, options);
                        break;
                    }
                    catch (HttpRequestException ex) when
                        ((ex.Data.Contains("SETTINGS_ENABLE_CONNECT_PROTOCOL") || ex.Data.Contains("HTTP2_ENABLED")) &&
                        tryDowngrade &&
                        (options.HttpVersion == HttpVersion.Version11 || options.HttpVersionPolicy == HttpVersionPolicy.RequestVersionOrLower))
                    {
                    }
                }

                // The SecWebSocketProtocol header is optional.  We should only get it with a non-empty value if we requested subprotocols,
                // and then it must only be one of the ones we requested.  If we got a subprotocol other than one we requested (or if we
                // already got one in a previous header), fail. Otherwise, track which one we got.
                string?subprotocol = null;
                if (response.Headers.TryGetValues(HttpKnownHeaderNames.SecWebSocketProtocol, out IEnumerable <string>?subprotocolEnumerableValues))
                {
                    Debug.Assert(subprotocolEnumerableValues is string[]);
                    string[] subprotocolArray = (string[])subprotocolEnumerableValues;
                    if (subprotocolArray.Length > 0 && !string.IsNullOrEmpty(subprotocolArray[0]))
                    {
                        if (options._requestedSubProtocols is not null)
                        {
                            foreach (string requestedProtocol in options._requestedSubProtocols)
                            {
                                if (requestedProtocol.Equals(subprotocolArray[0], StringComparison.OrdinalIgnoreCase))
                                {
                                    subprotocol = requestedProtocol;
                                    break;
                                }
                            }
                        }

                        if (subprotocol == null)
                        {
                            throw new WebSocketException(
                                      WebSocketError.UnsupportedProtocol,
                                      SR.Format(SR.net_WebSockets_AcceptUnsupportedProtocol, string.Join(", ", options.RequestedSubProtocols), string.Join(", ", subprotocolArray)));
                        }
                    }
                }

                // Because deflate options are negotiated we need a new object
                WebSocketDeflateOptions?negotiatedDeflateOptions = null;

                if (options.DangerousDeflateOptions is not null && response.Headers.TryGetValues(HttpKnownHeaderNames.SecWebSocketExtensions, out IEnumerable <string>?extensions))
                {
                    foreach (ReadOnlySpan <char> extension in extensions)
                    {
                        if (extension.TrimStart().StartsWith(ClientWebSocketDeflateConstants.Extension))
                        {
                            negotiatedDeflateOptions = ParseDeflateOptions(extension, options.DangerousDeflateOptions);
                            break;
                        }
                    }
                }

                // Get the response stream and wrap it in a web socket.
                Stream connectedStream = response.Content.ReadAsStream();
                Debug.Assert(connectedStream.CanWrite);
                Debug.Assert(connectedStream.CanRead);
                WebSocket = WebSocket.CreateFromStream(connectedStream, new WebSocketCreationOptions
                {
                    IsServer                = false,
                    SubProtocol             = subprotocol,
                    KeepAliveInterval       = options.KeepAliveInterval,
                    DangerousDeflateOptions = negotiatedDeflateOptions
                });
                _negotiatedDeflateOptions = negotiatedDeflateOptions;
            }
            catch (Exception exc)
            {
                if (_state < WebSocketState.Closed)
                {
                    _state = WebSocketState.Closed;
                }

                Abort();
                disposeResponse = true;

                if (exc is WebSocketException ||
                    (exc is OperationCanceledException && cancellationToken.IsCancellationRequested))
                {
                    throw;
                }

                throw new WebSocketException(WebSocketError.Faulted, SR.net_webstatus_ConnectFailure, exc);
            }
            finally
            {
                if (response is not null)
                {
                    if (options.CollectHttpResponseDetails)
                    {
                        HttpStatusCode      = response.StatusCode;
                        HttpResponseHeaders = new HttpResponseHeadersReadOnlyCollection(response.Headers);
                    }

                    if (disposeResponse)
                    {
                        response.Dispose();
                    }
                }

                // Disposing the handler will not affect any active stream wrapped in the WebSocket.
                if (disposeHandler)
                {
                    invoker?.Dispose();
                }
            }
        }
Example #13
0
 public void Tearown()
 {
     _httpMessageInvoker.Dispose();
     _httpServer.Dispose();
 }
 protected override void Dispose(bool disposing)
 {
     (_tokenManager as IDisposable)?.Dispose();
     _httpMessageInvoker.Dispose();
     base.Dispose(disposing);
 }
Example #15
0
 public void Dispose()
 {
     invoker.Dispose();
 }
Example #16
0
 public void TearDown()
 {
     invoker.Dispose();
 }
Example #17
0
 /// <inheritdoc />
 protected override void Dispose(bool disposing)
 {
     _httpMessageInvoker.Dispose();
     base.Dispose(disposing);
 }
Example #18
0
 public void Dispose()
 {
     invoker.Dispose();
     authenticationHandler.Dispose();
     testHttpMessageHandler.Dispose();
 }
Example #19
0
 public void Dispose() => _sender.Dispose();