From 5eae687ddd2f1a297b39a4099fa52e9280517a33 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Sat, 9 Sep 2017 11:47:20 -0700 Subject: [PATCH] Updated EnableCorsAttribute and UseCors extension to not have to supply a policy name. --- .../EnableCorsAttribute.cs | 11 ++- .../Infrastructure/CorsMiddleware.cs | 14 ++++ .../CorsMiddlewareExtensions.cs | 15 +++++ .../Infrastructure/CorsOptions.cs | 28 ++++++++ .../CorsMiddlewareTests.cs | 52 ++++++++++++++ .../CorsOptionsTest.cs | 67 +++++++++++++++++++ 6 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 test/Microsoft.AspNetCore.Cors.Test/CorsOptionsTest.cs diff --git a/src/Microsoft.AspNetCore.Cors/EnableCorsAttribute.cs b/src/Microsoft.AspNetCore.Cors/EnableCorsAttribute.cs index 34bd269d96..b19851e39a 100644 --- a/src/Microsoft.AspNetCore.Cors/EnableCorsAttribute.cs +++ b/src/Microsoft.AspNetCore.Cors/EnableCorsAttribute.cs @@ -11,7 +11,16 @@ namespace Microsoft.AspNetCore.Cors public class EnableCorsAttribute : Attribute, IEnableCorsAttribute { /// - /// Creates a new instance of the . + /// Creates a new instance of the with the default policy + /// name defined by . + /// + public EnableCorsAttribute() + : this(policyName: null) + { + } + + /// + /// Creates a new instance of the with the supplied policy name. /// /// The name of the policy to be applied. public EnableCorsAttribute(string policyName) diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs index a5dd632d38..eb773f5abf 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddleware.cs @@ -19,6 +19,20 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure private readonly CorsPolicy _policy; private readonly string _corsPolicyName; + /// + /// Instantiates a new . + /// + /// The next middleware in the pipeline. + /// An instance of . + /// A policy provider which can get an . + public CorsMiddleware( + RequestDelegate next, + ICorsService corsService, + ICorsPolicyProvider policyProvider) + : this(next, corsService, policyProvider, policyName: null) + { + } + /// /// Instantiates a new . /// diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddlewareExtensions.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddlewareExtensions.cs index aae7ca4602..dea1ad01d9 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddlewareExtensions.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsMiddlewareExtensions.cs @@ -11,6 +11,21 @@ namespace Microsoft.AspNetCore.Builder /// public static class CorsMiddlewareExtensions { + /// + /// Adds a CORS middleware to your web application pipeline to allow cross domain requests. + /// + /// The IApplicationBuilder passed to your Configure method + /// The original app parameter + public static IApplicationBuilder UseCors(this IApplicationBuilder app) + { + if (app == null) + { + throw new ArgumentNullException(nameof(app)); + } + + return app.UseMiddleware(); + } + /// /// Adds a CORS middleware to your web application pipeline to allow cross domain requests. /// diff --git a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsOptions.cs b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsOptions.cs index 10b046000d..92e1f775ba 100644 --- a/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsOptions.cs +++ b/src/Microsoft.AspNetCore.Cors/Infrastructure/CorsOptions.cs @@ -31,6 +31,34 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure } } + /// + /// Adds a new policy and sets it as the default. + /// + /// The policy to be added. + public void AddDefaultPolicy(CorsPolicy policy) + { + if (policy == null) + { + throw new ArgumentNullException(nameof(policy)); + } + + AddPolicy(DefaultPolicyName, policy); + } + + /// + /// Adds a new policy and sets it as the default. + /// + /// A delegate which can use a policy builder to build a policy. + public void AddDefaultPolicy(Action configurePolicy) + { + if (configurePolicy == null) + { + throw new ArgumentNullException(nameof(configurePolicy)); + } + + AddPolicy(DefaultPolicyName, configurePolicy); + } + /// /// Adds a new policy. /// diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs index 01a2c2d8e3..d74c020eae 100644 --- a/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsMiddlewareTests.cs @@ -297,5 +297,57 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure o => o.GetPolicyAsync(It.IsAny(), It.IsAny()), Times.Once); } + + [Fact] + public async Task PreFlight_MatchesDefaultPolicy_SetsResponseHeaders() + { + // Arrange + var hostBuilder = new WebHostBuilder() + .Configure(app => + { + app.UseCors(); + app.Run(async context => + { + await context.Response.WriteAsync("Cross origin response"); + }); + }) + .ConfigureServices(services => + { + services.AddCors(options => + { + options.AddDefaultPolicy(policyBuilder => + { + policyBuilder + .WithOrigins("http://localhost:5001") + .WithMethods("PUT") + .WithHeaders("Header1") + .WithExposedHeaders("AllowedHeader") + .Build(); + }); + options.AddPolicy("policy2", policyBuilder => + { + policyBuilder + .WithOrigins("http://localhost:5002") + .Build(); + }); + }); + }); + + using (var server = new TestServer(hostBuilder)) + { + // Act + // Preflight request. + var response = await server.CreateRequest("/") + .AddHeader(CorsConstants.Origin, "http://localhost:5001") + .AddHeader(CorsConstants.AccessControlRequestMethod, "PUT") + .SendAsync(CorsConstants.PreflightHttpMethod); + + // Assert + response.EnsureSuccessStatusCode(); + Assert.Equal(2, response.Headers.Count()); + Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault()); + Assert.Equal("PUT", response.Headers.GetValues(CorsConstants.AccessControlAllowMethods).FirstOrDefault()); + } + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Cors.Test/CorsOptionsTest.cs b/test/Microsoft.AspNetCore.Cors.Test/CorsOptionsTest.cs new file mode 100644 index 0000000000..360231d38b --- /dev/null +++ b/test/Microsoft.AspNetCore.Cors.Test/CorsOptionsTest.cs @@ -0,0 +1,67 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Xunit; + +namespace Microsoft.AspNetCore.Cors.Infrastructure +{ + public class CorsOptionsTest + { + [Fact] + public void AddDefaultPolicy_SetsDefaultPolicyName() + { + // Arrange + var corsOptions = new CorsOptions(); + var expectedPolicy = new CorsPolicy(); + + // Act + corsOptions.AddPolicy("policy1", new CorsPolicy()); + corsOptions.AddDefaultPolicy(expectedPolicy); + corsOptions.AddPolicy("policy3", new CorsPolicy()); + + // Assert + var actualPolicy = corsOptions.GetPolicy(corsOptions.DefaultPolicyName); + Assert.Same(expectedPolicy, actualPolicy); + } + + [Fact] + public void AddDefaultPolicy_OverridesDefaultPolicyName() + { + // Arrange + var corsOptions = new CorsOptions(); + var expectedPolicy = new CorsPolicy(); + + // Act + corsOptions.AddDefaultPolicy(new CorsPolicy()); + corsOptions.AddDefaultPolicy(expectedPolicy); + + // Assert + var actualPolicy = corsOptions.GetPolicy(corsOptions.DefaultPolicyName); + Assert.Same(expectedPolicy, actualPolicy); + } + + [Fact] + public void AddDefaultPolicy_UsingPolicyBuilder_SetsDefaultPolicyName() + { + // Arrange + var corsOptions = new CorsOptions(); + CorsPolicy expectedPolicy = null; + + // Act + corsOptions.AddPolicy("policy1", policyBuilder => + { + policyBuilder.AllowAnyOrigin().Build(); + }); + corsOptions.AddDefaultPolicy(policyBuilder => + { + expectedPolicy = policyBuilder.AllowAnyOrigin().Build(); + }); + corsOptions.AddPolicy("policy3", new CorsPolicy()); + + // Assert + var actualPolicy = corsOptions.GetPolicy(corsOptions.DefaultPolicyName); + Assert.Same(expectedPolicy, actualPolicy); + } + } +} \ No newline at end of file