/// <inheritdoc /> public CorsResult EvaluatePolicy(HttpContext context, CorsPolicy policy) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (policy == null) { throw new ArgumentNullException(nameof(policy)); } var corsResult = new CorsResult(); var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod]; if (string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.Ordinal) && !StringValues.IsNullOrEmpty(accessControlRequestMethod)) { EvaluatePreflightRequest(context, policy, corsResult); } else { EvaluateRequest(context, policy, corsResult); } return corsResult; }
public virtual void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result) { var origin = context.Request.Headers[CorsConstants.Origin]; if (StringValues.IsNullOrEmpty(origin) || !policy.AllowAnyOrigin && !policy.Origins.Contains(origin)) { return; } AddOriginToResult(origin, policy, result); result.SupportsCredentials = policy.SupportsCredentials; AddHeaderValues(result.AllowedExposedHeaders, policy.ExposedHeaders); }
public void Default_Constructor() { // Arrange & Act var result = new CorsResult(); // Assert Assert.Empty(result.AllowedHeaders); Assert.Empty(result.AllowedExposedHeaders); Assert.Empty(result.AllowedMethods); Assert.False(result.SupportsCredentials); Assert.Null(result.AllowedOrigin); Assert.Null(result.PreflightMaxAge); }
public void SettingNegativePreflightMaxAge_Throws() { // Arrange var result = new CorsResult(); // Act var exception = Assert.Throws<ArgumentOutOfRangeException>(() => { result.PreflightMaxAge = TimeSpan.FromSeconds(-1); }); // Assert Assert.Equal( $"PreflightMaxAge must be greater than or equal to 0.{Environment.NewLine}Parameter name: value", exception.Message); }
public void ToString_ReturnsThePropertyValues() { // Arrange var corsResult = new CorsResult { SupportsCredentials = true, PreflightMaxAge = TimeSpan.FromSeconds(30), AllowedOrigin = "*" }; corsResult.AllowedExposedHeaders.Add("foo"); corsResult.AllowedHeaders.Add("bar"); corsResult.AllowedHeaders.Add("baz"); corsResult.AllowedMethods.Add("GET"); // Act var result = corsResult.ToString(); // Assert Assert.Equal( @"AllowCredentials: True, PreflightMaxAge: 30, AllowOrigin: *," + " AllowExposedHeaders: {foo}, AllowHeaders: {bar,baz}, AllowMethods: {GET}", result); }
public void ApplyResult_SomeSimpleAllowHeaders_AllowHeadersHeaderAddedForNonSimpleHeaders() { // Arrange var result = new CorsResult(); result.AllowedHeaders.Add("Content-Language"); result.AllowedHeaders.Add("foo"); result.AllowedHeaders.Add("bar"); result.AllowedHeaders.Add("Accept"); var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.Contains("Access-Control-Allow-Headers", httpContext.Response.Headers.Keys); string[] headerValues = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Allow-Headers"); Assert.Equal(2, headerValues.Length); Assert.Contains("foo", headerValues); Assert.Contains("bar", headerValues); }
private void AddOriginToResult(string origin, CorsPolicy policy, CorsResult result) { if (policy.AllowAnyOrigin) { if (policy.SupportsCredentials) { result.AllowedOrigin = origin; result.VaryByOrigin = true; } else { result.AllowedOrigin = CorsConstants.AnyOrigin; } } else if (policy.Origins.Contains(origin)) { result.AllowedOrigin = origin; } }
/// <inheritdoc /> public virtual void ApplyResult(CorsResult result, HttpResponse response) { if (result == null) { throw new ArgumentNullException(nameof(result)); } if (response == null) { throw new ArgumentNullException(nameof(response)); } var headers = response.Headers; if (result.AllowedOrigin != null) { headers[CorsConstants.AccessControlAllowOrigin] = result.AllowedOrigin; } if (result.VaryByOrigin) { headers["Vary"] = "Origin"; } if (result.SupportsCredentials) { headers[CorsConstants.AccessControlAllowCredentials] = "true"; } if (result.AllowedMethods.Count > 0) { // Filter out simple methods var nonSimpleAllowMethods = result.AllowedMethods .Where(m => !CorsConstants.SimpleMethods.Contains(m, StringComparer.OrdinalIgnoreCase)) .ToArray(); if (nonSimpleAllowMethods.Length > 0) { headers.SetCommaSeparatedValues( CorsConstants.AccessControlAllowMethods, nonSimpleAllowMethods); } } if (result.AllowedHeaders.Count > 0) { // Filter out simple request headers var nonSimpleAllowRequestHeaders = result.AllowedHeaders .Where(header => !CorsConstants.SimpleRequestHeaders.Contains(header, StringComparer.OrdinalIgnoreCase)) .ToArray(); if (nonSimpleAllowRequestHeaders.Length > 0) { headers.SetCommaSeparatedValues( CorsConstants.AccessControlAllowHeaders, nonSimpleAllowRequestHeaders); } } if (result.AllowedExposedHeaders.Count > 0) { // Filter out simple response headers var nonSimpleAllowResponseHeaders = result.AllowedExposedHeaders .Where(header => !CorsConstants.SimpleResponseHeaders.Contains(header, StringComparer.OrdinalIgnoreCase)) .ToArray(); if (nonSimpleAllowResponseHeaders.Length > 0) { headers.SetCommaSeparatedValues( CorsConstants.AccessControlExposeHeaders, nonSimpleAllowResponseHeaders); } } if (result.PreflightMaxAge.HasValue) { headers[CorsConstants.AccessControlMaxAge] = result.PreflightMaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture); } }
public void ApplyResult_PreflightMaxAge_MaxAgeHeaderAdded() { // Arrange var result = new CorsResult { PreflightMaxAge = TimeSpan.FromSeconds(30) }; var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.Equal("30", httpContext.Response.Headers["Access-Control-Max-Age"]); }
public void ApplyResult_NoPreflightMaxAge_MaxAgeHeaderNotAdded() { // Arrange var result = new CorsResult { PreflightMaxAge = null }; var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.DoesNotContain("Access-Control-Max-Age", httpContext.Response.Headers.Keys); }
public void ApplyResult_ManyAllowExposedHeaders_ExposedHeadersHeaderAdded() { // Arrange var result = new CorsResult(); result.AllowedExposedHeaders.Add("foo"); result.AllowedExposedHeaders.Add("bar"); result.AllowedExposedHeaders.Add("baz"); var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.Contains("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys); var value = Assert.Single(httpContext.Response.Headers.Values); Assert.Equal(new[] { "foo,bar,baz" }, value); string[] exposedHeaderValues = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Expose-Headers"); Assert.Equal(3, exposedHeaderValues.Length); Assert.Contains("foo", exposedHeaderValues); Assert.Contains("bar", exposedHeaderValues); Assert.Contains("baz", exposedHeaderValues); }
public void ApplyResult_AllowOrigin_AllowOriginHeaderAdded() { // Arrange var result = new CorsResult { AllowedOrigin = "http://example.com" }; var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.Equal("http://example.com", httpContext.Response.Headers["Access-Control-Allow-Origin"]); }
public void ApplyResult_AllowCredentials_AllowCredentialsHeaderAdded() { // Arrange var result = new CorsResult { SupportsCredentials = true }; var service = new CorsService(new TestCorsOptions()); // Act var httpContext = new DefaultHttpContext(); service.ApplyResult(result, httpContext.Response); // Assert Assert.Equal("true", httpContext.Response.Headers["Access-Control-Allow-Credentials"]); }
public void ApplyResult_NoAllowOrigin_AllowOriginHeaderNotAdded() { // Arrange var result = new CorsResult { AllowedOrigin = null }; var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.DoesNotContain("Access-Control-Allow-Origin", httpContext.Response.Headers.Keys); }
public void ApplyResult_SimpleAllowMethods_AllowMethodsHeaderNotAdded() { // Arrange var result = new CorsResult(); result.AllowedMethods.Add("GET"); result.AllowedMethods.Add("HEAD"); result.AllowedMethods.Add("POST"); var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.DoesNotContain("Access-Control-Allow-Methods", httpContext.Response.Headers.Keys); }
public void ApplyResult_SomeSimpleAllowMethods_AllowMethodsHeaderAddedForNonSimpleMethods() { // Arrange var result = new CorsResult(); result.AllowedMethods.Add("PUT"); result.AllowedMethods.Add("get"); result.AllowedMethods.Add("DELETE"); result.AllowedMethods.Add("POST"); var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.Contains("Access-Control-Allow-Methods", httpContext.Response.Headers.Keys); var value = Assert.Single(httpContext.Response.Headers.Values); Assert.Equal(new[] { "PUT,DELETE" }, value); string[] methods = httpContext.Response.Headers.GetCommaSeparatedValues("Access-Control-Allow-Methods"); Assert.Equal(2, methods.Length); Assert.Contains("PUT", methods); Assert.Contains("DELETE", methods); }
public void ApplyResult_OneAllowMethods_AllowMethodsHeaderAdded() { // Arrange var result = new CorsResult(); result.AllowedMethods.Add("PUT"); var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.Equal("PUT", httpContext.Response.Headers["Access-Control-Allow-Methods"]); }
public void ApplyResult_NoAllowCredentials_AllowCredentialsHeaderNotAdded() { // Arrange var result = new CorsResult { SupportsCredentials = false }; var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.DoesNotContain("Access-Control-Allow-Credentials", httpContext.Response.Headers.Keys); }
public void ApplyResult_AddVaryHeader_VaryHeaderAdded() { // Arrange var result = new CorsResult { VaryByOrigin = true }; var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.Equal("Origin", httpContext.Response.Headers["Vary"]); }
public virtual void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result) { var origin = context.Request.Headers[CorsConstants.Origin]; if (StringValues.IsNullOrEmpty(origin) || !policy.AllowAnyOrigin && !policy.Origins.Contains(origin)) { return; } var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod]; if (StringValues.IsNullOrEmpty(accessControlRequestMethod)) { return; } var requestHeaders = context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders); if (!policy.AllowAnyMethod && !policy.Methods.Contains(accessControlRequestMethod)) { return; } if (!policy.AllowAnyHeader && requestHeaders != null && !requestHeaders.All(header => CorsConstants.SimpleRequestHeaders.Contains(header, StringComparer.OrdinalIgnoreCase) || policy.Headers.Contains(header, StringComparer.OrdinalIgnoreCase))) { return; } AddOriginToResult(origin, policy, result); result.SupportsCredentials = policy.SupportsCredentials; result.PreflightMaxAge = policy.PreflightMaxAge; result.AllowedMethods.Add(accessControlRequestMethod); AddHeaderValues(result.AllowedHeaders, requestHeaders); }
public void ApplyResult_SimpleAllowHeaders_AllowHeadersHeaderNotAdded() { // Arrange var result = new CorsResult(); result.AllowedHeaders.Add("Accept"); result.AllowedHeaders.Add("Accept-Language"); result.AllowedHeaders.Add("Content-Language"); var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.DoesNotContain("Access-Control-Allow-Headers", httpContext.Response.Headers.Keys); }
public void ApplyResult_NoAllowExposedHeaders_ExposedHeadersHeaderNotAdded() { // Arrange var result = new CorsResult { // AllowExposedHeaders is empty by default }; var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.DoesNotContain("Access-Control-Expose-Headers", httpContext.Response.Headers.Keys); }
public void ApplyResult_OneAllowExposedHeaders_ExposedHeadersHeaderAdded() { // Arrange var result = new CorsResult(); result.AllowedExposedHeaders.Add("foo"); var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.Equal("foo", httpContext.Response.Headers["Access-Control-Expose-Headers"]); }
private CorsResult GetCorsResult( string origin = null, IList<string> headers = null, IList<string> methods = null, IList<string> exposedHeaders = null, long? preFlightMaxAge = null, bool? supportsCredentials = null) { var result = new CorsResult(); if (origin != null) { result.AllowedOrigin = origin; } if (headers != null) { AddRange(result.AllowedHeaders, headers); } if (methods != null) { AddRange(result.AllowedMethods, methods); } if (exposedHeaders != null) { AddRange(result.AllowedExposedHeaders, exposedHeaders); } if (preFlightMaxAge != null) { result.PreflightMaxAge = TimeSpan.FromSeconds(preFlightMaxAge.Value); } if (supportsCredentials != null) { result.SupportsCredentials = supportsCredentials.Value; } return result; }
public void ApplyResult_ReturnsNoHeaders_ByDefault() { // Arrange var result = new CorsResult(); var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert Assert.Empty(httpContext.Response.Headers); }