public async Task NoOptionsCall_WithRoute_MatchingOrigin_Test() { var httpContext = new DefaultHttpContext(); httpContext.Request.Method = "POST"; httpContext.Request.Headers.Add(HeaderNames.Origin, "http://origin-host"); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { AllowOrigins = new List <string> { "http://origin-host" } } }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); Assert.IsTrue(httpContext.Response.Headers.ContainsKey(HeaderNames.AccessControlAllowOrigin)); Assert.AreEqual(httpContext.Request.Headers[HeaderNames.Origin], httpContext.Response.Headers[HeaderNames.AccessControlAllowOrigin]); A.CallTo(() => _next(httpContext)) .MustHaveHappened(); }
public async Task RequiredClaims_WithAuthentication_Must_CallNext_Test() { var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim> { new Claim("Claim", "value"), new Claim("Claim", "12345") }, "basic")); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { RequireAuthentication = false, RequiredClaims = new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("Claim", "^[a-z]+$"), new KeyValuePair <string, string>("Claim", "^[0-9]+$") } } }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); A.CallTo(() => _next(httpContext)).MustHaveHappened(); }
public async Task RequiredClaims_WithAuthentication_And_InvalidClaim_Must_Return401_Test() { var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim> { new Claim("Claim", "value") }, "basic")); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { RequireAuthentication = false, RequiredClaims = new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("Claim", "[0-9]+"), new KeyValuePair <string, string>("Claim", "[a-z]+") } } }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); A.CallTo(() => _next(httpContext)).MustNotHaveHappened(); Assert.AreEqual(StatusCodes.Status401Unauthorized, httpContext.Response.StatusCode); }
public async Task HttpAsyncError_StartedResponse_Must_Return_ResponseStatusCode() { var httpContext = new DefaultHttpContext(); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition() }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); var httpResponseFeature = A.Fake<IHttpResponseFeature>(); A.CallTo(() => httpResponseFeature.HasStarted).Returns(true); A.CallTo(() => httpResponseFeature.StatusCode).Returns(StatusCodes.Status200OK); httpContext.Features.Set(httpResponseFeature); A.CallTo(() => _publisherService.HttpAsync(A<RouteDefinitionMatch>.Ignored, A<HttpContext>.Ignored)) .Throws(new Exception()); await _middleware.InvokeAsync(httpContext); A.CallTo(() => httpResponseFeature.HasStarted).MustHaveHappened(); Assert.AreEqual(StatusCodes.Status200OK, httpContext.Response.StatusCode); }
public async Task HttpAsync(RouteDefinitionMatch routeDefinitionMatch, HttpContext httpContext) { if (routeDefinitionMatch?.RouteDefinition?.RouteEndpoints == null) { throw new ArgumentException("Invalid route definition", nameof(routeDefinitionMatch)); } if (routeDefinitionMatch.RouteDefinition.RouteEndpoints.Count == 0) { throw new ArgumentException("Route definition must contains at least 1 RouteEndpoint", nameof(routeDefinitionMatch)); } var originIpAddress = httpContext.GetOriginIpAddress(); if (originIpAddress == null) { throw new ArgumentException("Origin IP Address is null", nameof(httpContext)); } var ipHashIndex = originIpAddress.GetHashIndex(); var endpointId = ipHashIndex % routeDefinitionMatch.RouteDefinition.RouteEndpoints.Count; var endpointStr = routeDefinitionMatch.RouteDefinition.RouteEndpoints[endpointId].RenderTemplate(routeDefinitionMatch.Values); var endpoint = new Uri(endpointStr); var clientId = $"{endpoint.Host}"; var httpClient = _httpClients.GetOrAdd(clientId, _ => _httpClientFactory.CreateClient()); var httpRequestMessage = httpContext.Request.ToHttpRequestMessage(endpoint); if (routeDefinitionMatch.RouteDefinition.ClaimMappings != null) { foreach (var(claimType, headerName) in routeDefinitionMatch.RouteDefinition.ClaimMappings) { var claims = httpContext.User.Claims.Where(c => c.Type == claimType); foreach (var claim in claims) { httpRequestMessage.Headers.Add(headerName, claim.Value); } } } if (httpContext.Connection.RemoteIpAddress != null) { httpRequestMessage.Headers.Add(HttpHeaderNames.XForwardedFor, httpContext.Connection.RemoteIpAddress.ToString()); } var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead, httpContext.RequestAborted); await httpResponseMessage.PopulateHttpResponseAsync(httpContext.Response, httpContext.RequestAborted); }
public async Task InvalidRouteDefinitionMatch_Must_Return500_Test() { var httpContext = new DefaultHttpContext(); var routeDefinitionMatch = new RouteDefinitionMatch(); httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); Assert.AreEqual(StatusCodes.Status500InternalServerError, httpContext.Response.StatusCode); }
public async Task InvalidRouteDefinitionMatch_Must_Throw_ArgumentException_Test() { var routeDefinitionMatch = new RouteDefinitionMatch(); var httpContext = new DefaultHttpContext(); httpContext.Connection.RemoteIpAddress = new IPAddress(new byte[] { 0, 0, 0, 0 }); var ex = await Assert.ThrowsExceptionAsync <ArgumentException>(() => _publisherService.HttpAsync(routeDefinitionMatch, httpContext)); Assert.AreEqual("routeDefinitionMatch", ex.ParamName); }
public async Task RouteDefinitionMatch_WithHttpEndpoint_Must_CallHttp_Test() { var httpContext = new DefaultHttpContext(); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition() }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); A.CallTo(() => _publisherService.HttpAsync(routeDefinitionMatch, httpContext)).MustHaveHappened(); }
public async Task CallToEndpoint_Test() { var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { RouteEndpoints = new List <string> { "http://test-host" }, ClaimMappings = new Dictionary <string, string> { { "Claim1", "Header-Claim1" }, { "Claim2", "Header-Claim2" } } } }; var httpContext = new DefaultHttpContext(); httpContext.Connection.RemoteIpAddress = new IPAddress(new byte[] { 0, 0, 0, 0 }); httpContext.Request.Method = HttpMethods.Get; httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim> { new Claim("Claim1", "Claim-Value") })); HttpRequestMessage requestArgument = null; A.CallTo(_httpMessageHandler) .Where(m => m.Method.Name == "SendAsync") .WithReturnType <Task <HttpResponseMessage> >() .Invokes((call) => { requestArgument = (HttpRequestMessage)call.Arguments[0]; }) .Returns(new HttpResponseMessage { Content = new StringContent("") }); await _publisherService.HttpAsync(routeDefinitionMatch, httpContext); A.CallTo(_httpMessageHandler) .Where(m => m.Method.Name == "SendAsync") .WithReturnType <Task <HttpResponseMessage> >() .MustHaveHappened(); Assert.IsTrue(requestArgument.Headers.Any(h => h.Key == HttpHeaderNames.XForwardedFor && h.Value.Contains("0.0.0.0"))); Assert.IsTrue(requestArgument.Headers.Any(h => h.Key == "Header-Claim1" && h.Value.Contains("Claim-Value"))); }
public async Task ValidRouteDefinitionMatch_Must_CallNext_Test() { var httpContext = new DefaultHttpContext(); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition() }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); A.CallTo(() => _next(httpContext)).MustHaveHappened(); }
public async Task RequireAuthentication_Must_Return401_Test() { var httpContext = new DefaultHttpContext(); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { RequireAuthentication = true } }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); Assert.AreEqual(StatusCodes.Status401Unauthorized, httpContext.Response.StatusCode); }
public async Task NullOriginIpAddress_Must_Throw_ArgumentException_Test() { var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { RouteEndpoints = new List <string> { "http://test-host" } } }; var httpContext = new DefaultHttpContext(); var ex = await Assert.ThrowsExceptionAsync <ArgumentException>(() => _publisherService.HttpAsync(routeDefinitionMatch, httpContext)); Assert.AreEqual("httpContext", ex.ParamName); }
public async Task HttpAsyncError_WithNoStartedResponse_Must_Return_502StatusCode() { var httpContext = new DefaultHttpContext(); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition() }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); A.CallTo(() => _publisherService.HttpAsync(A<RouteDefinitionMatch>.Ignored, A<HttpContext>.Ignored)) .Throws(new Exception()); await _middleware.InvokeAsync(httpContext); Assert.AreEqual(StatusCodes.Status502BadGateway, httpContext.Response.StatusCode); }
public async Task RequireAuthentication_Must_CallNext_Test() { var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity("basic")); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { RequireAuthentication = true } }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); A.CallTo(() => _next(httpContext)).MustHaveHappened(); }
public async Task <RouteDefinitionMatch> MatchAsync(string pathString, string method) { await LoadRouteDefinitionsAsync(); var routeTemplateMatch = _routeTemplateCollection.Match(pathString); var routeDefinition = routeTemplateMatch?.Item.SingleOrDefault(rd => rd.RouteMethods.Contains(method)); if (routeDefinition == null) { return(null); } var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = routeDefinition, Values = routeTemplateMatch.Values }; return(routeDefinitionMatch); }
public async Task RequiredClaims_WithNoAuthentication_Must_CallNext_Test() { var httpContext = new DefaultHttpContext(); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { RequireAuthentication = false, RequiredClaims = new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("Claim", "Value") } } }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); A.CallTo(() => _next(httpContext)).MustHaveHappened(); }
public async Task OptionsCall_WithRoute_MatchingOrigin_Test() { var httpContext = new DefaultHttpContext(); httpContext.Request.Method = HttpMethods.Options; httpContext.Request.Headers.Add(HeaderNames.Origin, "http://origin-host"); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { RouteMethods = new List <string> { "POST", "PUT" }, AllowOrigins = new List <string> { "http://origin-host" } } }; A.CallTo(() => _routeDefinitionMatcher.MatchAsync(A <string> .Ignored, A <string> .Ignored)) .Returns(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); A.CallTo(() => _next(httpContext)) .MustNotHaveHappened(); Assert.IsTrue(httpContext.Response.Headers.ContainsKey(HeaderNames.AccessControlAllowOrigin)); Assert.AreEqual(httpContext.Request.Headers[HeaderNames.Origin], httpContext.Response.Headers[HeaderNames.AccessControlAllowOrigin]); Assert.IsTrue(httpContext.Response.Headers.ContainsKey(HeaderNames.AccessControlAllowMethods)); foreach (var method in routeDefinitionMatch.RouteDefinition.RouteMethods) { Assert.IsTrue(httpContext.Response.Headers[HeaderNames.AccessControlAllowMethods].Contains(method)); } Assert.AreEqual(StatusCodes.Status204NoContent, httpContext.Response.StatusCode); }
public async Task RequiredClaims_WithAuthentication_And_NoClaims_Must_Return401_Test() { var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity("basic")); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { RequireAuthentication = false, RequiredClaims = new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("Claim", "Value") } } }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); Assert.AreEqual(StatusCodes.Status401Unauthorized, httpContext.Response.StatusCode); }
public async Task MappedClaims_InRequestHeaders_Must_Return403_Test() { var httpContext = new DefaultHttpContext(); httpContext.Request.Headers.Add(new KeyValuePair <string, StringValues>("Mapped-Claim-Header", "value")); var routeDefinitionMatch = new RouteDefinitionMatch { RouteDefinition = new RouteDefinition { ClaimMappings = new Dictionary <string, string> { { "Claim", "Mapped-Claim-Header" } } } }; httpContext.SetRouteDefinitionMatch(routeDefinitionMatch); await _middleware.InvokeAsync(httpContext); A.CallTo(() => _next(httpContext)).MustNotHaveHappened(); Assert.AreEqual(StatusCodes.Status403Forbidden, httpContext.Response.StatusCode); }
public static void SetRouteDefinitionMatch(this HttpContext httpContext, RouteDefinitionMatch routeDefinitionMatch) { httpContext.Items.Add("routeDefinitionMatch", routeDefinitionMatch); }