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(")); }
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]); }
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(")); }
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(")); }
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); } }
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)); }
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))); }
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); } }