private async Task InvokeCore(HttpContext context) { var corsPolicy = _policy ?? await _corsPolicyProvider?.GetPolicyAsync(context, _corsPolicyName); if (corsPolicy == null) { Logger?.NoCorsPolicyFound(); await _next(context); return; } var corsResult = CorsService.EvaluatePolicy(context, corsPolicy); if (corsResult.IsPreflightRequest) { CorsService.ApplyResult(corsResult, context.Response); // Since there is a policy which was identified, // always respond to preflight requests. context.Response.StatusCode = StatusCodes.Status204NoContent; return; } else { context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult)); await _next(context); } }
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_SimpleRequests_IgnoresFiltering() { // Arrange var result = new CorsResult(); result.AllowedHeaders.Add("Content-Type"); result.AllowedHeaders.Add("Date"); result.AllowedMethods.Add("GET"); result.AllowedMethods.Add("PUT"); var httpContext = new DefaultHttpContext(); var service = new CorsService(new TestCorsOptions()); // Act service.ApplyResult(result, httpContext.Response); // Assert string[] arMethods = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowMethods); Assert.Contains("GET", arMethods); Assert.Contains("PUT", arMethods); string[] arHeaders = httpContext.Response.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlAllowHeaders); Assert.Contains("Content-Type", arHeaders); Assert.Contains("Date", arHeaders); }
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); }
private Task EvaluateAndApplyPolicy(HttpContext context, CorsPolicy corsPolicy) { if (corsPolicy == null) { Logger.NoCorsPolicyFound(); return(_next(context)); } var corsResult = CorsService.EvaluatePolicy(context, corsPolicy); if (corsResult.IsPreflightRequest) { CorsService.ApplyResult(corsResult, context.Response); // Since there is a policy which was identified, // always respond to preflight requests. context.Response.StatusCode = StatusCodes.Status204NoContent; return(Task.CompletedTask); } else { context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult)); return(_next(context)); } }
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); }
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_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"]); }
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_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_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 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_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_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_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_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_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_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 async Task InvokeCore(HttpContext context, ICorsPolicyProvider corsPolicyProvider) { // CORS policy resolution rules: // // 1. If there is an endpoint with IDisableCorsAttribute then CORS is not run // 2. If there is an endpoint with ICorsPolicyMetadata then use its policy or if // there is an endpoint with IEnableCorsAttribute that has a policy name then // fetch policy by name, prioritizing it above policy on middleware // 3. If there is no policy on middleware then use name on middleware // Flag to indicate to other systems, e.g. MVC, that CORS middleware was run for this request context.Items[CorsMiddlewareInvokedKey] = CorsMiddlewareInvokedValue; var endpoint = context.GetEndpoint(); // Get the most significant CORS metadata for the endpoint // For backwards compatibility reasons this is then downcast to Enable/Disable metadata var corsMetadata = endpoint?.Metadata.GetMetadata <ICorsMetadata>(); if (corsMetadata is IDisableCorsAttribute) { await _next(context); return; } var corsPolicy = _policy; var policyName = _corsPolicyName; if (corsMetadata is ICorsPolicyMetadata corsPolicyMetadata) { policyName = null; corsPolicy = corsPolicyMetadata.Policy; } else if (corsMetadata is IEnableCorsAttribute enableCorsAttribute && enableCorsAttribute.PolicyName != null) { // If a policy name has been provided on the endpoint metadata then prioritizing it above the static middleware policy policyName = enableCorsAttribute.PolicyName; corsPolicy = null; } if (corsPolicy == null) { // Resolve policy by name if the local policy is not being used corsPolicy = await corsPolicyProvider.GetPolicyAsync(context, policyName); } if (corsPolicy == null) { Logger?.NoCorsPolicyFound(); await _next(context); return; } var corsResult = CorsService.EvaluatePolicy(context, corsPolicy); if (corsResult.IsPreflightRequest) { CorsService.ApplyResult(corsResult, context.Response); // Since there is a policy which was identified, // always respond to preflight requests. context.Response.StatusCode = StatusCodes.Status204NoContent; return; } else { context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult)); await _next(context); } }
private async Task InvokeCore(HttpContext context, ICorsPolicyProvider corsPolicyProvider) { // CORS policy resolution rules: // // 1. If there is an endpoint with IDisableCorsAttribute then CORS is not run // 2. If there is an endpoint with ICorsPolicyMetadata then use its policy or if // there is an endpoint with IEnableCorsAttribute that has a policy name then // fetch policy by name, prioritizing it above policy on middleware // 3. If there is no policy on middleware then use name on middleware var endpoint = context.GetEndpoint(); // Get the most significant CORS metadata for the endpoint // For backwards compatibility reasons this is then downcast to Enable/Disable metadata var corsMetadata = endpoint?.Metadata.GetMetadata <ICorsMetadata>(); if (corsMetadata is IDisableCorsAttribute) { var isOptionsRequest = string.Equals( context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase); var isCorsPreflightRequest = isOptionsRequest && context.Request.Headers.ContainsKey(CorsConstants.AccessControlRequestMethod); if (isCorsPreflightRequest) { // If this is a preflight request, and we disallow CORS, complete the request context.Response.StatusCode = StatusCodes.Status204NoContent; return; } await _next(context); return; } var corsPolicy = _policy; var policyName = _corsPolicyName; if (corsMetadata is ICorsPolicyMetadata corsPolicyMetadata) { policyName = null; corsPolicy = corsPolicyMetadata.Policy; } else if (corsMetadata is IEnableCorsAttribute enableCorsAttribute && enableCorsAttribute.PolicyName != null) { // If a policy name has been provided on the endpoint metadata then prioritizing it above the static middleware policy policyName = enableCorsAttribute.PolicyName; corsPolicy = null; } if (corsPolicy == null) { // Resolve policy by name if the local policy is not being used corsPolicy = await corsPolicyProvider.GetPolicyAsync(context, policyName); } if (corsPolicy == null) { Logger?.NoCorsPolicyFound(); await _next(context); return; } var corsResult = CorsService.EvaluatePolicy(context, corsPolicy); if (corsResult.IsPreflightRequest) { CorsService.ApplyResult(corsResult, context.Response); // Since there is a policy which was identified, // always respond to preflight requests. context.Response.StatusCode = StatusCodes.Status204NoContent; return; } else { context.Response.OnStarting(OnResponseStartingDelegate, Tuple.Create(this, context, corsResult)); await _next(context); } }