public void RequestingSignalrHubsUrlWithTrailingSlashReturnsProxy(string proxyUrl)
        {
            // Arrange
            var serviceProvider = CreateServiceProvider();
            var dispatcher = new HubDispatcher(serviceProvider.GetRequiredService<IOptions<SignalROptions>>());
            var testContext = new TestContext(proxyUrl + "/");

            // Act
            dispatcher.Initialize(serviceProvider);
            dispatcher.ProcessRequest(testContext.MockHttpContext.Object).Wait();

            // Assert
            Assert.Equal("application/javascript; charset=UTF-8", testContext.ResponseContentType);
            Assert.Equal(1, testContext.ResponseBuffer.Count);
            Assert.NotNull(testContext.ResponseBuffer[0]);
            Assert.False(testContext.ResponseBuffer[0].StartsWith("throw new Error("));
        }
        public void RequestingSignalrHubsUrlWithJavaScriptProxiesDesabledDoesNotReturnProxy(string proxyUrl)
        {
            // Arrange
            var serviceProvider = CreateServiceProvider();
            var optionsAccessor = serviceProvider.GetRequiredService<IOptions<SignalROptions>>();
            optionsAccessor.Options.Hubs.EnableJavaScriptProxies = false;
            var dispatcher = new HubDispatcher(optionsAccessor);
            var testContext = new TestContext(proxyUrl);

            // Act
            dispatcher.Initialize(serviceProvider);
            dispatcher.ProcessRequest(testContext.MockHttpContext.Object).Wait();

            // Assert
            Assert.Equal("application/javascript; charset=UTF-8", testContext.ResponseContentType);
            Assert.Equal(1, testContext.ResponseBuffer.Count);
            Assert.True(testContext.ResponseBuffer[0].StartsWith("throw new Error("));
        }
        public override Task Invoke(IOwinContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (JsonUtility.TryRejectJSONPRequest(_configuration, context))
            {
                return TaskAsyncHelper.Empty;
            }

            var dispatcher = new HubDispatcher(_configuration);

            dispatcher.Initialize(_configuration.Resolver);

            return dispatcher.ProcessRequest(context.Environment);
        }
        public void RequestingSignalrHubsUrlWithTrailingSlashReturnsProxy(string proxyUrl)
        {
            // Arrange
            var dispatcher = new HubDispatcher(new HubConfiguration());
            var request = GetRequestForUrl(proxyUrl);
            var response = new Mock<IResponse>();
            string contentType = null;
            var buffer = new List<string>();
            response.SetupSet(m => m.ContentType = It.IsAny<string>()).Callback<string>(type => contentType = type);
            response.Setup(m => m.Write(It.IsAny<ArraySegment<byte>>())).Callback<ArraySegment<byte>>(data => buffer.Add(Encoding.UTF8.GetString(data.Array, data.Offset, data.Count)));

            // Act
            var context = new HostContext(request.Object, response.Object);
            dispatcher.Initialize(new DefaultDependencyResolver());
            dispatcher.ProcessRequest(context).Wait();

            // Assert
            Assert.Equal("application/javascript; charset=UTF-8", contentType);
            Assert.Equal(1, buffer.Count);
            Assert.NotNull(buffer[0]);
            Assert.False(buffer[0].StartsWith("throw new Error("));
        }
Esempio n. 5
0
        public void RequestingSignalrHubsUrlWithTrailingSlashReturnsProxy()
        {
            // Arrange
            var dispatcher = new HubDispatcher("/signalr");
            var request = GetRequestForUrl("http://something/signalr/hubs/");
            var response = new Mock<IResponse>();
            string contentType = null;
            var buffer = new List<string>();
            response.SetupSet(m => m.ContentType = It.IsAny<string>()).Callback<string>(type => contentType = type);
            response.Setup(m => m.Write(It.IsAny<ArraySegment<byte>>())).Callback<ArraySegment<byte>>(data => buffer.Add(Encoding.UTF8.GetString(data.Array, data.Offset, data.Count)));
            response.Setup(m => m.EndAsync()).Returns(TaskAsyncHelper.Empty);

            // Act
            var context = new HostContext(request.Object, response.Object);
            dispatcher.Initialize(new DefaultDependencyResolver(), context);
            dispatcher.ProcessRequestAsync(context).Wait();

            // Assert
            Assert.Equal("application/x-javascript", contentType);
            Assert.Equal(1, buffer.Count);
            Assert.NotNull(buffer[0]);
        }
Esempio n. 6
0
        public void RequestingSignalrHubsUrlWithJavaScriptProxiesDesabledDoesNotReturnProxy()
        {
            // Arrange
            var dispatcher = new HubDispatcher(new HubConfiguration() { EnableJavaScriptProxies = false });
            var request = GetRequestForUrl("http://something/signalr/hubs");
            var response = new Mock<IResponse>();
            string contentType = null;
            var buffer = new List<string>();
            response.SetupSet(m => m.ContentType = It.IsAny<string>()).Callback<string>(type => contentType = type);
            response.Setup(m => m.Write(It.IsAny<ArraySegment<byte>>())).Callback<ArraySegment<byte>>(data => buffer.Add(Encoding.UTF8.GetString(data.Array, data.Offset, data.Count)));
            response.Setup(m => m.End()).Returns(TaskAsyncHelper.Empty);

            // Act
            var context = new HostContext(request.Object, response.Object);
            dispatcher.Initialize(new DefaultDependencyResolver(), context);
            dispatcher.ProcessRequest(context).Wait();

            // Assert
            Assert.Equal("application/javascript; charset=UTF-8", contentType);
            Assert.Equal(1, buffer.Count);
            Assert.True(buffer[0].StartsWith("throw new Error("));
        }
Esempio n. 7
0
        public void RequestingSignalrHubsUrlReturnsProxy(string proxyUrl)
        {
            // Arrange
            var    dispatcher  = new HubDispatcher(new HubConfiguration());
            var    request     = GetRequestForUrl(proxyUrl);
            var    response    = new Mock <IResponse>();
            string contentType = null;
            var    buffer      = new List <string>();

            response.SetupSet(m => m.ContentType = It.IsAny <string>()).Callback <string>(type => contentType = type);
            response.Setup(m => m.Write(It.IsAny <ArraySegment <byte> >())).Callback <ArraySegment <byte> >(data => buffer.Add(Encoding.UTF8.GetString(data.Array, data.Offset, data.Count)));

            // Act
            var context = new HostContext(request.Object, response.Object);

            dispatcher.Initialize(new DefaultDependencyResolver());
            dispatcher.ProcessRequest(context).Wait();

            // Assert
            Assert.Equal("application/javascript; charset=UTF-8", contentType);
            Assert.Equal(1, buffer.Count);
            Assert.NotNull(buffer[0]);
            Assert.False(buffer[0].StartsWith("throw new Error("));
        }
Esempio n. 8
0
        public void DuplicateHubNamesThrows()
        {
            // Arrange
            var dispatcher = new HubDispatcher(new HubConfiguration());
            var request    = new Mock <IRequest>();
            var qs         = new NameValueCollection();

            request.Setup(m => m.QueryString).Returns(new NameValueCollectionWrapper(qs));
            qs["connectionData"] = @"[{name: ""foo""}, {name: ""Foo""}]";

            var mockHub        = new Mock <IHub>();
            var mockHubManager = new Mock <IHubManager>();

            mockHubManager.Setup(m => m.GetHub("foo")).Returns(new HubDescriptor {
                Name = "foo", HubType = mockHub.Object.GetType()
            });

            var dr = new DefaultDependencyResolver();

            dr.Register(typeof(IHubManager), () => mockHubManager.Object);

            dispatcher.Initialize(dr);
            Assert.Throws <InvalidOperationException>(() => dispatcher.Authorize(request.Object));
        }
        public void DetailedErrorsAreDisabledByDefault()
        {
            // Arrange
            var serviceProvider = CreateServiceProvider();
            var dispatcher = new HubDispatcher(serviceProvider.GetRequiredService<IOptions<SignalROptions>>());
            var testContext = new TestContext("/signalr/send", new Dictionary<string, string>
            {
                {"transport", "longPolling"},
                {"connectionToken", "0"},
                {"data", "{\"H\":\"ErrorHub\",\"M\":\"Error\",\"A\":[],\"I\":0}"}
            });

            // Act
            dispatcher.Initialize(serviceProvider);
            dispatcher.ProcessRequest(testContext.MockHttpContext.Object).Wait();

            var json = JsonSerializer.Create(new JsonSerializerSettings());

            // Assert
            Assert.Equal("application/json; charset=UTF-8", testContext.ResponseContentType);
            Assert.True(testContext.ResponseBuffer.Count > 0);

            using (var reader = new StringReader(String.Join(String.Empty, testContext.ResponseBuffer)))
            {
                var hubResponse = (HubResponse)json.Deserialize(reader, typeof(HubResponse));
                Assert.Contains("ErrorHub.Error", hubResponse.Error);
                Assert.DoesNotContain("Custom", hubResponse.Error);
            }
        }
Esempio n. 10
0
        public void DuplicateHubNamesThrows()
        {
            // Arrange
            var mockHub = new Mock<IHub>();
            var mockHubManager = new Mock<IHubManager>();
            mockHubManager.Setup(m => m.GetHub("foo")).Returns(new HubDescriptor { Name = "foo", HubType = mockHub.Object.GetType() });

            var serviceProvider = ServiceProviderHelper.CreateServiceProvider(services => services.AddInstance(mockHubManager.Object));

            var dispatcher = new HubDispatcher(serviceProvider.GetRequiredService<IOptions<SignalROptions>>());
            var testContext = new TestContext("/ignorePath", new Dictionary<string, string>
            {
                {"connectionData", @"[{name: ""foo""}, {name: ""Foo""}]"},
            });

            // Act & Assert
            dispatcher.Initialize(serviceProvider);
            Assert.Throws<InvalidOperationException>(() => dispatcher.Authorize(testContext.MockRequest.Object));
        }
        public void DuplicateHubNamesThrows()
        {
            // Arrange
            var dispatcher = new HubDispatcher(new HubConfiguration());
            var request = new Mock<IRequest>();
            var qs = new NameValueCollection();
            request.Setup(m => m.QueryString).Returns(new NameValueCollectionWrapper(qs));
            qs["connectionData"] = @"[{name: ""foo""}, {name: ""Foo""}]";

            var mockHub = new Mock<IHub>();
            var mockHubManager = new Mock<IHubManager>();
            mockHubManager.Setup(m => m.GetHub("foo")).Returns(new HubDescriptor { Name = "foo", HubType = mockHub.Object.GetType() });

            var dr = new DefaultDependencyResolver();
            dr.Register(typeof(IHubManager), () => mockHubManager.Object);

            dispatcher.Initialize(dr);
            Assert.Throws<InvalidOperationException>(() => dispatcher.Authorize(request.Object));
        }
        public void DetailedErrorsFromFaultedTasksCanBeEnabled()
        {
            // Arrange
            var dispatcher = new HubDispatcher(new HubConfiguration() { EnableDetailedErrors = true });

            var request = GetRequestForUrl("http://something/signalr/send");
            request.Setup(m => m.QueryString).Returns(new NameValueCollectionWrapper(new NameValueCollection()
                                                      {
                                                          {"transport", "longPolling"},
                                                          {"connectionToken", "0"},
                                                          {"data", "{\"H\":\"ErrorHub\",\"M\":\"ErrorTask\",\"A\":[],\"I\":0}"}
                                                      }));

            request.Setup(m => m.ReadForm()).Returns(Task.FromResult<INameValueCollection>(new NameValueCollectionWrapper()));

            string contentType = null;
            var buffer = new List<string>();

            var response = new Mock<IResponse>();
            response.SetupGet(m => m.CancellationToken).Returns(CancellationToken.None);
            response.SetupSet(m => m.ContentType = It.IsAny<string>()).Callback<string>(type => contentType = type);
            response.Setup(m => m.Write(It.IsAny<ArraySegment<byte>>())).Callback<ArraySegment<byte>>(data => buffer.Add(Encoding.UTF8.GetString(data.Array, data.Offset, data.Count)));

            // Act
            var context = new HostContext(request.Object, response.Object);
            var resolver = new DefaultDependencyResolver();
            resolver.Register(typeof(IProtectedData), () => new EmptyProtectedData());
            resolver.Register(typeof(ErrorHub), () => new ErrorHub());
            dispatcher.Initialize(resolver);

            dispatcher.ProcessRequest(context).Wait();

            var json = JsonSerializer.Create(new JsonSerializerSettings());


            // Assert
            Assert.Equal("application/json; charset=UTF-8", contentType);
            Assert.True(buffer.Count > 0);

            using (var reader = new StringReader(String.Join(String.Empty, buffer)))
            {
                var hubResponse = (HubResponse)json.Deserialize(reader, typeof(HubResponse));
                Assert.Equal("Custom Error from task.", hubResponse.Error);
            }
        }
        private Task ProcessNegotiationRequest(IOwinContext owinContext, HostContext context)
        {
            var claims = BuildClaims(owinContext, context.Request);

            var dispatcher = new HubDispatcher(_configuration);

            try
            {
                dispatcher.Initialize(_configuration.Resolver);
                if (!dispatcher.Authorize(context.Request))
                {
                    string error = null;
                    if (context.Request.User != null && context.Request.User.Identity.IsAuthenticated)
                    {
                        // If the user is authenticated and authorize failed then 403
                        error = "Forbidden";
                        context.Response.StatusCode = 403;
                    }
                    else
                    {
                        // If failed to authorize the request then return 401
                        error = "Unauthorized";
                        context.Response.StatusCode = 401;
                    }
                    Log.NegotiateFailed(_logger, error);
                    return(context.Response.End(error));
                }
            }
            catch (Exception e)
            {
                Log.NegotiateFailed(_logger, e.Message);
                context.Response.StatusCode = 500;
                return(context.Response.End(""));
            }

            IServiceEndpointProvider provider;

            try
            {
                // Take the service endpoints for the app
                provider = _endpointManager.GetEndpointProvider(_router.GetNegotiateEndpoint(owinContext, _endpointManager.GetEndpoints(_appName)));

                // When status code changes, we consider the inner router changed the response, then we stop here
                if (context.Response.StatusCode != 200)
                {
                    // Inner handler already write to context.Response, no need to continue with error case
                    return(Task.CompletedTask);
                }

                // Consider it as internal server error when we don't successfully get negotiate response
                if (provider == null)
                {
                    var message = "Unable to get the negotiate endpoint";
                    Log.NegotiateFailed(_logger, message);
                    context.Response.StatusCode = 500;
                    return(context.Response.End(message));
                }
            }
            catch (AzureSignalRNotConnectedException e)
            {
                Log.NegotiateFailed(_logger, e.Message);
                context.Response.StatusCode = 500;
                return(context.Response.End(e.Message));
            }

            // Redirect to Service
            var    clientProtocol = context.Request.QueryString["clientProtocol"];
            string originalPath   = null;
            string queryString    = null;

            // add OriginalPath and QueryString when the clients protocol is higher than 2.0, earlier ASP.NET SignalR clients does not support redirect URL with query parameters
            if (!string.IsNullOrEmpty(clientProtocol) && Version.TryParse(clientProtocol, out var version) && version >= ClientSupportQueryStringVersion)
            {
                var clientRequestId = _connectionRequestIdProvider.GetRequestId();
                if (clientRequestId != null)
                {
                    // remove system preserved query strings
                    queryString = "?" +
                                  string.Join("&",
                                              context.Request.QueryString.Where(s => !PreservedQueryParameters.Contains(s.Key)).Concat(
                                                  new[]
                    {
                        new KeyValuePair <string, string>(
                            Constants.QueryParameter.ConnectionRequestId,
                            clientRequestId)
                    })
                                              .Select(s => $"{Uri.EscapeDataString(s.Key)}={Uri.EscapeDataString(s.Value)}"));
                }

                originalPath = GetOriginalPath(context.Request.LocalPath);
            }

            var url = provider.GetClientEndpoint(null, originalPath, queryString);

            return(GenerateClientAccessTokenAsync(provider, context, url, claims));
        }
Esempio n. 14
0
        private Task ProcessNegotiationRequest(IOwinContext owinContext, HostContext context)
        {
            string accessToken = null;
            var    claims      = BuildClaims(owinContext, context.Request);

            var dispatcher = new HubDispatcher(_configuration);

            try
            {
                dispatcher.Initialize(_configuration.Resolver);
                if (!dispatcher.Authorize(context.Request))
                {
                    string error = null;
                    if (context.Request.User != null && context.Request.User.Identity.IsAuthenticated)
                    {
                        // If the user is authenticated and authorize failed then 403
                        error = "Forbidden";
                        context.Response.StatusCode = 403;
                    }
                    else
                    {
                        // If failed to authorize the request then return 401
                        error = "Unauthorized";
                        context.Response.StatusCode = 401;
                    }
                    Log.NegotiateFailed(_logger, error);
                    return(context.Response.End(error));
                }
            }
            catch (Exception e)
            {
                Log.NegotiateFailed(_logger, e.Message);
                context.Response.StatusCode = 500;
                return(context.Response.End(""));
            }

            IServiceEndpointProvider provider;

            try
            {
                provider = _endpointManager.GetEndpointProvider(_router.GetNegotiateEndpoint(owinContext, _endpointManager.Endpoints));

                // When status code changes, we consider the inner router changed the response, then we stop here
                if (context.Response.StatusCode != 200)
                {
                    // Inner handler already write to context.Response, no need to continue with error case
                    return(Task.CompletedTask);
                }

                // Consider it as internal server error when we don't successfully get negotiate response
                if (provider == null)
                {
                    var message = "Unable to get the negotiate endpoint";
                    Log.NegotiateFailed(_logger, message);
                    context.Response.StatusCode = 500;
                    return(context.Response.End(message));
                }
            }
            catch (AzureSignalRNotConnectedException e)
            {
                Log.NegotiateFailed(_logger, e.Message);
                context.Response.StatusCode = 500;
                return(context.Response.End(e.Message));
            }

            // Redirect to Service
            // TODO: add OriginalPath and QueryString when the clients support it
            var url = provider.GetClientEndpoint(null, null, null);

            try
            {
                accessToken = provider.GenerateClientAccessToken(null, claims);
            }
            catch (AzureSignalRAccessTokenTooLongException ex)
            {
                Log.NegotiateFailed(_logger, ex.Message);
                context.Response.StatusCode = 413;
                return(context.Response.End(ex.Message));
            }

            return(SendJsonResponse(context, GetRedirectNegotiateResponse(url, accessToken)));
        }
Esempio n. 15
0
        public void DetailedErrorsAreDisabledByDefault()
        {
            // Arrange
            var dispatcher = new HubDispatcher(new HubConfiguration());

            var request = new Mock<IRequest>();
            request.Setup(m => m.Url).Returns(new Uri("http://something/signalr/send"));
            request.Setup(m => m.QueryString).Returns(new NameValueCollection()
                                                      {
                                                          {"transport", "longPolling"},
                                                          {"connectionToken", "0"},
                                                          {"data", "{\"H\":\"ErrorHub\",\"M\":\"Error\",\"A\":[],\"I\":0}"}
                                                      });
            request.Setup(m => m.Form).Returns(new NameValueCollection());

            string contentType = null;
            var buffer = new List<string>();

            var response = new Mock<IResponse>();
            response.SetupGet(m => m.CancellationToken).Returns(CancellationToken.None);
            response.SetupSet(m => m.ContentType = It.IsAny<string>()).Callback<string>(type => contentType = type);
            response.Setup(m => m.Write(It.IsAny<ArraySegment<byte>>())).Callback<ArraySegment<byte>>(data => buffer.Add(Encoding.UTF8.GetString(data.Array, data.Offset, data.Count)));
            response.Setup(m => m.End()).Returns(TaskAsyncHelper.Empty);

            // Act
            var context = new HostContext(request.Object, response.Object);
            var resolver = new DefaultDependencyResolver();
            resolver.Register(typeof(IProtectedData), () => new EmptyProtectedData());
            resolver.Register(typeof(ErrorHub), () => new ErrorHub());
            dispatcher.Initialize(resolver, context);

            dispatcher.ProcessRequest(context).Wait();

            var json = JsonSerializer.Create(new JsonSerializerSettings());


            // Assert
            Assert.Equal("application/json; charset=UTF-8", contentType);
            Assert.Equal(1, buffer.Count);
            Assert.NotNull(buffer[0]);

            using (var reader = new StringReader(buffer[0]))
            {
                var hubResponse = (HubResponse)json.Deserialize(reader, typeof(HubResponse));
                Assert.Contains("ErrorHub.Error", hubResponse.Error);
                Assert.DoesNotContain("Custom", hubResponse.Error);
            }
        }