Update CORS middleware to use endpoint metadata (#4460)
This commit is contained in:
parent
6187e628af
commit
6dc28d8a4e
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
@ -16,10 +17,31 @@ namespace SampleDestination
|
||||||
.UseUrls("http://+:9000")
|
.UseUrls("http://+:9000")
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
.ConfigureLogging(factory => factory.AddConsole())
|
.ConfigureLogging(factory => factory.AddConsole())
|
||||||
.UseStartup<Startup>()
|
.UseStartup(GetStartupType())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
host.Run();
|
host.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Type GetStartupType()
|
||||||
|
{
|
||||||
|
var startup = Environment.GetEnvironmentVariable("CORS_STARTUP");
|
||||||
|
if (startup == null)
|
||||||
|
{
|
||||||
|
return typeof(Startup);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (startup)
|
||||||
|
{
|
||||||
|
case "Startup":
|
||||||
|
return typeof(Startup);
|
||||||
|
case "StartupWithoutEndpointRouting":
|
||||||
|
return typeof(StartupWithoutEndpointRouting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Could not resolve the startup type. Unexpected CORS_STARTUP environment variable.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -26,66 +25,70 @@ namespace SampleDestination
|
||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddCors();
|
services.AddCors(options =>
|
||||||
}
|
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
|
||||||
{
|
|
||||||
app.Map("/allow-origin", innerBuilder =>
|
|
||||||
{
|
{
|
||||||
innerBuilder.UseCors(policy => policy
|
options.AddPolicy("AllowOrigin", policy => policy
|
||||||
.WithOrigins(DefaultAllowedOrigin)
|
.WithOrigins(DefaultAllowedOrigin)
|
||||||
.AllowAnyMethod()
|
.AllowAnyMethod()
|
||||||
.AllowAnyHeader());
|
.AllowAnyHeader());
|
||||||
|
|
||||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
options.AddPolicy("AllowHeaderMethod", policy => policy
|
||||||
});
|
|
||||||
|
|
||||||
app.Map("/allow-header-method", innerBuilder =>
|
|
||||||
{
|
|
||||||
innerBuilder.UseCors(policy => policy
|
|
||||||
.WithOrigins(DefaultAllowedOrigin)
|
.WithOrigins(DefaultAllowedOrigin)
|
||||||
.WithHeaders("X-Test", "Content-Type")
|
.WithHeaders("X-Test", "Content-Type")
|
||||||
.WithMethods("PUT"));
|
.WithMethods("PUT"));
|
||||||
|
|
||||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
options.AddPolicy("AllowCredentials", policy => policy
|
||||||
});
|
|
||||||
|
|
||||||
app.Map("/allow-credentials", innerBuilder =>
|
|
||||||
{
|
|
||||||
innerBuilder.UseCors(policy => policy
|
|
||||||
.WithOrigins(DefaultAllowedOrigin)
|
.WithOrigins(DefaultAllowedOrigin)
|
||||||
.AllowAnyHeader()
|
.AllowAnyHeader()
|
||||||
.WithMethods("GET", "PUT")
|
.WithMethods("GET", "PUT")
|
||||||
.AllowCredentials());
|
.AllowCredentials());
|
||||||
|
|
||||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
options.AddPolicy("ExposedHeader", policy => policy
|
||||||
});
|
|
||||||
|
|
||||||
app.Map("/exposed-header", innerBuilder =>
|
|
||||||
{
|
|
||||||
innerBuilder.UseCors(policy => policy
|
|
||||||
.WithOrigins(DefaultAllowedOrigin)
|
.WithOrigins(DefaultAllowedOrigin)
|
||||||
.WithExposedHeaders("X-AllowedHeader", "Content-Length"));
|
.WithExposedHeaders("X-AllowedHeader", "Content-Length"));
|
||||||
|
|
||||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
options.AddPolicy("AllowAll", policy => policy
|
||||||
});
|
|
||||||
|
|
||||||
app.Map("/allow-all", innerBuilder =>
|
|
||||||
{
|
|
||||||
innerBuilder.UseCors(policy => policy
|
|
||||||
.AllowAnyOrigin()
|
.AllowAnyOrigin()
|
||||||
.AllowAnyMethod()
|
.AllowAnyMethod()
|
||||||
.AllowAnyHeader()
|
.AllowAnyHeader()
|
||||||
.AllowCredentials());
|
.AllowCredentials());
|
||||||
|
|
||||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
|
||||||
});
|
});
|
||||||
|
services.AddRouting();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
app.UseRouting(routing =>
|
||||||
|
{
|
||||||
|
routing.Map("/allow-origin", HandleRequest).WithCorsPolicy("AllowOrigin");
|
||||||
|
routing.Map("/allow-header-method", HandleRequest).WithCorsPolicy("AllowHeaderMethod");
|
||||||
|
routing.Map("/allow-credentials", HandleRequest).WithCorsPolicy("AllowCredentials");
|
||||||
|
routing.Map("/exposed-header", HandleRequest).WithCorsPolicy("ExposedHeader");
|
||||||
|
routing.Map("/allow-all", HandleRequest).WithCorsPolicy("AllowAll");
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseCors();
|
||||||
|
|
||||||
|
app.UseEndpoint();
|
||||||
|
|
||||||
app.Run(async (context) =>
|
app.Run(async (context) =>
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync("Hello World!");
|
await context.Response.WriteAsync("Hello World!");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Task HandleRequest(HttpContext context)
|
||||||
|
{
|
||||||
|
var content = Encoding.UTF8.GetBytes("Hello world");
|
||||||
|
|
||||||
|
context.Response.Headers["X-AllowedHeader"] = "Test-Value";
|
||||||
|
context.Response.Headers["X-DisallowedHeader"] = "Test-Value";
|
||||||
|
|
||||||
|
context.Response.ContentType = "text/plain; charset=utf-8";
|
||||||
|
context.Response.ContentLength = content.Length;
|
||||||
|
context.Response.Body.Write(content, 0, content.Length);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
// 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.Net;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace SampleDestination
|
||||||
|
{
|
||||||
|
public class StartupWithoutEndpointRouting
|
||||||
|
{
|
||||||
|
private static readonly string DefaultAllowedOrigin = $"http://{Dns.GetHostName()}:9001";
|
||||||
|
private readonly ILogger<StartupWithoutEndpointRouting> _logger;
|
||||||
|
|
||||||
|
public StartupWithoutEndpointRouting(ILoggerFactory loggerFactory)
|
||||||
|
{
|
||||||
|
_logger = loggerFactory.CreateLogger<StartupWithoutEndpointRouting>();
|
||||||
|
_logger.LogInformation($"Setting up CORS middleware to allow clients on {DefaultAllowedOrigin}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddCors();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||||
|
{
|
||||||
|
app.Map("/allow-origin", innerBuilder =>
|
||||||
|
{
|
||||||
|
innerBuilder.UseCors(policy => policy
|
||||||
|
.WithOrigins(DefaultAllowedOrigin)
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader());
|
||||||
|
|
||||||
|
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.Map("/allow-header-method", innerBuilder =>
|
||||||
|
{
|
||||||
|
innerBuilder.UseCors(policy => policy
|
||||||
|
.WithOrigins(DefaultAllowedOrigin)
|
||||||
|
.WithHeaders("X-Test", "Content-Type")
|
||||||
|
.WithMethods("PUT"));
|
||||||
|
|
||||||
|
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.Map("/allow-credentials", innerBuilder =>
|
||||||
|
{
|
||||||
|
innerBuilder.UseCors(policy => policy
|
||||||
|
.WithOrigins(DefaultAllowedOrigin)
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.WithMethods("GET", "PUT")
|
||||||
|
.AllowCredentials());
|
||||||
|
|
||||||
|
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.Map("/exposed-header", innerBuilder =>
|
||||||
|
{
|
||||||
|
innerBuilder.UseCors(policy => policy
|
||||||
|
.WithOrigins(DefaultAllowedOrigin)
|
||||||
|
.WithExposedHeaders("X-AllowedHeader", "Content-Length"));
|
||||||
|
|
||||||
|
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.Map("/allow-all", innerBuilder =>
|
||||||
|
{
|
||||||
|
innerBuilder.UseCors(policy => policy
|
||||||
|
.AllowAnyOrigin()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowCredentials());
|
||||||
|
|
||||||
|
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.Run(async (context) =>
|
||||||
|
{
|
||||||
|
await context.Response.WriteAsync("Hello World!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// 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 Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Cors
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Metadata that provides a CORS policy.
|
||||||
|
/// </summary>
|
||||||
|
public class CorsPolicyMetadata : ICorsPolicyMetadata
|
||||||
|
{
|
||||||
|
public CorsPolicyMetadata(CorsPolicy policy)
|
||||||
|
{
|
||||||
|
Policy = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The policy which needs to be applied.
|
||||||
|
/// </summary>
|
||||||
|
public CorsPolicy Policy { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
// 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 Microsoft.AspNetCore.Cors;
|
||||||
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Builder
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// CORS extension methods for <see cref="IEndpointConventionBuilder"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class CorsEndpointConventionBuilderExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a CORS policy with the specified name to the endpoint(s).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The endpoint convention builder.</param>
|
||||||
|
/// <param name="policyName">The CORS policy name.</param>
|
||||||
|
/// <returns>The original convention builder parameter.</returns>
|
||||||
|
public static IEndpointConventionBuilder WithCorsPolicy(this IEndpointConventionBuilder builder, string policyName)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Apply(endpointBuilder =>
|
||||||
|
{
|
||||||
|
endpointBuilder.Metadata.Add(new EnableCorsAttribute(policyName));
|
||||||
|
});
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified CORS policy to the endpoint(s).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The endpoint convention builder.</param>
|
||||||
|
/// <param name="configurePolicy">A delegate which can use a policy builder to build a policy.</param>
|
||||||
|
/// <returns>The original convention builder parameter.</returns>
|
||||||
|
public static IEndpointConventionBuilder WithCorsPolicy(this IEndpointConventionBuilder builder, Action<CorsPolicyBuilder> configurePolicy)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configurePolicy == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(configurePolicy));
|
||||||
|
}
|
||||||
|
|
||||||
|
var policyBuilder = new CorsPolicyBuilder();
|
||||||
|
configurePolicy(policyBuilder);
|
||||||
|
var policy = policyBuilder.Build();
|
||||||
|
|
||||||
|
builder.Apply(endpointBuilder =>
|
||||||
|
{
|
||||||
|
endpointBuilder.Metadata.Add(new CorsPolicyMetadata(policy));
|
||||||
|
});
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Cors.Internal;
|
using Microsoft.AspNetCore.Cors.Internal;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Endpoints;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
|
||||||
|
|
@ -15,6 +16,9 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CorsMiddleware
|
public class CorsMiddleware
|
||||||
{
|
{
|
||||||
|
// Property key is used by MVC filters to check if CORS middleware has run
|
||||||
|
private const string CorsMiddlewareInvokedKey = "__CorsMiddlewareInvoked";
|
||||||
|
|
||||||
private readonly Func<object, Task> OnResponseStartingDelegate = OnResponseStarting;
|
private readonly Func<object, Task> OnResponseStartingDelegate = OnResponseStarting;
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly CorsPolicy _policy;
|
private readonly CorsPolicy _policy;
|
||||||
|
|
@ -124,7 +128,49 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
|
|
||||||
private async Task InvokeCore(HttpContext context, ICorsPolicyProvider corsPolicyProvider)
|
private async Task InvokeCore(HttpContext context, ICorsPolicyProvider corsPolicyProvider)
|
||||||
{
|
{
|
||||||
var corsPolicy = _policy ?? await corsPolicyProvider.GetPolicyAsync(context, _corsPolicyName);
|
// 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] = true;
|
||||||
|
|
||||||
|
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)
|
if (corsPolicy == null)
|
||||||
{
|
{
|
||||||
Logger?.NoCorsPolicyFound();
|
Logger?.NoCorsPolicyFound();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A marker interface which can be used to identify CORS metdata.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICorsMetadata
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface which can be used to identify a type which provides metadata needed for enabling CORS support.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICorsPolicyMetadata : ICorsMetadata
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The policy which needs to be applied.
|
||||||
|
/// </summary>
|
||||||
|
CorsPolicy Policy { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An interface which can be used to identify a type which provides metdata to disable cors for a resource.
|
/// An interface which can be used to identify a type which provides metdata to disable cors for a resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDisableCorsAttribute
|
public interface IDisableCorsAttribute : ICorsMetadata
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An interface which can be used to identify a type which provides metadata needed for enabling CORS support.
|
/// An interface which can be used to identify a type which provides metadata needed for enabling CORS support.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IEnableCorsAttribute
|
public interface IEnableCorsAttribute : ICorsMetadata
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the policy which needs to be applied.
|
/// The name of the policy which needs to be applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string PolicyName { get; set; }
|
string PolicyName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>CORS middleware and policy for ASP.NET Core to enable cross-origin resource sharing.
|
<Description>CORS middleware and policy for ASP.NET Core to enable cross-origin resource sharing.
|
||||||
|
|
@ -13,6 +13,7 @@ Microsoft.AspNetCore.Cors.EnableCorsAttribute</Description>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.AspNetCore.Http.Extensions" />
|
<Reference Include="Microsoft.AspNetCore.Http.Extensions" />
|
||||||
|
<Reference Include="Microsoft.AspNetCore.Routing" />
|
||||||
<Reference Include="Microsoft.Extensions.Configuration.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Configuration.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,13 @@ namespace FunctionalTests
|
||||||
|
|
||||||
public ITestOutputHelper Output { get; }
|
public ITestOutputHelper Output { get; }
|
||||||
|
|
||||||
[Fact]
|
[Theory]
|
||||||
public async Task RunClientTests()
|
[InlineData("Startup")]
|
||||||
|
[InlineData("StartupWithoutEndpointRouting")]
|
||||||
|
public async Task RunClientTests(string startup)
|
||||||
{
|
{
|
||||||
using (StartLog(out var loggerFactory))
|
using (StartLog(out var loggerFactory))
|
||||||
using (var deploymentResult = await CreateDeployments(loggerFactory))
|
using (var deploymentResult = await CreateDeployments(loggerFactory, startup))
|
||||||
{
|
{
|
||||||
ProcessStartInfo processStartInfo;
|
ProcessStartInfo processStartInfo;
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
|
@ -58,7 +60,7 @@ namespace FunctionalTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<SamplesDeploymentResult> CreateDeployments(ILoggerFactory loggerFactory)
|
private static async Task<SamplesDeploymentResult> CreateDeployments(ILoggerFactory loggerFactory, string startup)
|
||||||
{
|
{
|
||||||
var solutionPath = TestPathUtilities.GetSolutionRootDirectory("Middleware");
|
var solutionPath = TestPathUtilities.GetSolutionRootDirectory("Middleware");
|
||||||
|
|
||||||
|
|
@ -78,6 +80,10 @@ namespace FunctionalTests
|
||||||
PublishApplicationBeforeDeployment = false,
|
PublishApplicationBeforeDeployment = false,
|
||||||
ApplicationType = ApplicationType.Portable,
|
ApplicationType = ApplicationType.Portable,
|
||||||
Configuration = configuration,
|
Configuration = configuration,
|
||||||
|
EnvironmentVariables =
|
||||||
|
{
|
||||||
|
["CORS_STARTUP"] = startup
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var destinationFactory = ApplicationDeployerFactory.Create(destinationParameters, loggerFactory);
|
var destinationFactory = ApplicationDeployerFactory.Create(destinationParameters, loggerFactory);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
// 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 System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
|
{
|
||||||
|
public class CorsEndpointConventionBuilderExtensionsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void WithCorsPolicy_Name_MetadataAdded()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testConventionBuilder = new TestEndpointConventionBuilder();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
testConventionBuilder.WithCorsPolicy("TestPolicyName");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var addCorsPolicy = Assert.Single(testConventionBuilder.Conventions);
|
||||||
|
|
||||||
|
var endpointModel = new TestEndpointModel();
|
||||||
|
addCorsPolicy(endpointModel);
|
||||||
|
var endpoint = endpointModel.Build();
|
||||||
|
|
||||||
|
var metadata = endpoint.Metadata.GetMetadata<IEnableCorsAttribute>();
|
||||||
|
Assert.NotNull(metadata);
|
||||||
|
Assert.Equal("TestPolicyName", metadata.PolicyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WithCorsPolicy_Policy_MetadataAdded()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testConventionBuilder = new TestEndpointConventionBuilder();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
testConventionBuilder.WithCorsPolicy(builder => builder.AllowAnyOrigin());
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var addCorsPolicy = Assert.Single(testConventionBuilder.Conventions);
|
||||||
|
|
||||||
|
var endpointModel = new TestEndpointModel();
|
||||||
|
addCorsPolicy(endpointModel);
|
||||||
|
var endpoint = endpointModel.Build();
|
||||||
|
|
||||||
|
var metadata = endpoint.Metadata.GetMetadata<ICorsPolicyMetadata>();
|
||||||
|
Assert.NotNull(metadata);
|
||||||
|
Assert.NotNull(metadata.Policy);
|
||||||
|
Assert.True(metadata.Policy.AllowAnyOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestEndpointModel : EndpointModel
|
||||||
|
{
|
||||||
|
public override Endpoint Build()
|
||||||
|
{
|
||||||
|
return new Endpoint(RequestDelegate, new EndpointMetadataCollection(Metadata), DisplayName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestEndpointConventionBuilder : IEndpointConventionBuilder
|
||||||
|
{
|
||||||
|
public IList<Action<EndpointModel>> Conventions { get; } = new List<Action<EndpointModel>>();
|
||||||
|
|
||||||
|
public void Apply(Action<EndpointModel> convention)
|
||||||
|
{
|
||||||
|
Conventions.Add(convention);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,8 +8,10 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Endpoints;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
using Microsoft.AspNetCore.TestHost;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -563,5 +565,256 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_HasEndpointWithNoMetadata_RunsCors()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var corsService = Mock.Of<ICorsService>();
|
||||||
|
var mockProvider = new Mock<ICorsPolicyProvider>();
|
||||||
|
var loggerFactory = NullLoggerFactory.Instance;
|
||||||
|
mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
|
||||||
|
.Returns(Task.FromResult<CorsPolicy>(null))
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
var middleware = new CorsMiddleware(
|
||||||
|
Mock.Of<RequestDelegate>(),
|
||||||
|
corsService,
|
||||||
|
loggerFactory,
|
||||||
|
"DefaultPolicyName");
|
||||||
|
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.SetEndpoint(new Endpoint(c => Task.CompletedTask, EndpointMetadataCollection.Empty, "Test endpoint"));
|
||||||
|
httpContext.Request.Headers.Add(CorsConstants.Origin, new[] { "http://example.com" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await middleware.Invoke(httpContext, mockProvider.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mockProvider.Verify(
|
||||||
|
o => o.GetPolicyAsync(It.IsAny<HttpContext>(), "DefaultPolicyName"),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_HasEndpointWithEnableMetadata_MiddlewareHasPolicyName_RunsCorsWithPolicyName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var corsService = Mock.Of<ICorsService>();
|
||||||
|
var mockProvider = new Mock<ICorsPolicyProvider>();
|
||||||
|
var loggerFactory = NullLoggerFactory.Instance;
|
||||||
|
mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
|
||||||
|
.Returns(Task.FromResult<CorsPolicy>(null))
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
var middleware = new CorsMiddleware(
|
||||||
|
Mock.Of<RequestDelegate>(),
|
||||||
|
corsService,
|
||||||
|
loggerFactory,
|
||||||
|
"DefaultPolicyName");
|
||||||
|
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new EnableCorsAttribute("MetadataPolicyName")), "Test endpoint"));
|
||||||
|
httpContext.Request.Headers.Add(CorsConstants.Origin, new[] { "http://example.com" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await middleware.Invoke(httpContext, mockProvider.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mockProvider.Verify(
|
||||||
|
o => o.GetPolicyAsync(It.IsAny<HttpContext>(), "MetadataPolicyName"),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_HasEndpointWithEnableMetadata_MiddlewareHasPolicy_RunsCorsWithPolicyName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var policy = new CorsPolicyBuilder().Build();
|
||||||
|
var corsService = Mock.Of<ICorsService>();
|
||||||
|
var mockProvider = new Mock<ICorsPolicyProvider>();
|
||||||
|
var loggerFactory = NullLoggerFactory.Instance;
|
||||||
|
mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
|
||||||
|
.Returns(Task.FromResult<CorsPolicy>(null))
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
var middleware = new CorsMiddleware(
|
||||||
|
Mock.Of<RequestDelegate>(),
|
||||||
|
corsService,
|
||||||
|
policy,
|
||||||
|
loggerFactory);
|
||||||
|
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new EnableCorsAttribute("MetadataPolicyName")), "Test endpoint"));
|
||||||
|
httpContext.Request.Headers.Add(CorsConstants.Origin, new[] { "http://example.com" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await middleware.Invoke(httpContext, mockProvider.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mockProvider.Verify(
|
||||||
|
o => o.GetPolicyAsync(It.IsAny<HttpContext>(), "MetadataPolicyName"),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_HasEndpointWithCorsPolicyMetadata_MiddlewareHasPolicy_RunsCorsWithPolicyName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var defaultPolicy = new CorsPolicyBuilder().Build();
|
||||||
|
var metadataPolicy = new CorsPolicyBuilder().Build();
|
||||||
|
var mockCorsService = new Mock<ICorsService>();
|
||||||
|
var mockProvider = new Mock<ICorsPolicyProvider>();
|
||||||
|
var loggerFactory = NullLoggerFactory.Instance;
|
||||||
|
mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
|
||||||
|
.Returns(Task.FromResult<CorsPolicy>(null))
|
||||||
|
.Verifiable();
|
||||||
|
mockCorsService.Setup(o => o.EvaluatePolicy(It.IsAny<HttpContext>(), It.IsAny<CorsPolicy>()))
|
||||||
|
.Returns(new CorsResult())
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
var middleware = new CorsMiddleware(
|
||||||
|
Mock.Of<RequestDelegate>(),
|
||||||
|
mockCorsService.Object,
|
||||||
|
defaultPolicy,
|
||||||
|
loggerFactory);
|
||||||
|
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new CorsPolicyMetadata(metadataPolicy)), "Test endpoint"));
|
||||||
|
httpContext.Request.Headers.Add(CorsConstants.Origin, new[] { "http://example.com" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await middleware.Invoke(httpContext, mockProvider.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mockProvider.Verify(
|
||||||
|
o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()),
|
||||||
|
Times.Never);
|
||||||
|
mockCorsService.Verify(
|
||||||
|
o => o.EvaluatePolicy(It.IsAny<HttpContext>(), metadataPolicy),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_HasEndpointWithEnableMetadataWithNoName_RunsCorsWithStaticPolicy()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var policy = new CorsPolicyBuilder().Build();
|
||||||
|
var mockCorsService = new Mock<ICorsService>();
|
||||||
|
var mockProvider = new Mock<ICorsPolicyProvider>();
|
||||||
|
var loggerFactory = NullLoggerFactory.Instance;
|
||||||
|
mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
|
||||||
|
.Returns(Task.FromResult<CorsPolicy>(null))
|
||||||
|
.Verifiable();
|
||||||
|
mockCorsService.Setup(o => o.EvaluatePolicy(It.IsAny<HttpContext>(), It.IsAny<CorsPolicy>()))
|
||||||
|
.Returns(new CorsResult())
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
var middleware = new CorsMiddleware(
|
||||||
|
Mock.Of<RequestDelegate>(),
|
||||||
|
mockCorsService.Object,
|
||||||
|
policy,
|
||||||
|
loggerFactory);
|
||||||
|
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new EnableCorsAttribute()), "Test endpoint"));
|
||||||
|
httpContext.Request.Headers.Add(CorsConstants.Origin, new[] { "http://example.com" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await middleware.Invoke(httpContext, mockProvider.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mockProvider.Verify(
|
||||||
|
o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()),
|
||||||
|
Times.Never);
|
||||||
|
mockCorsService.Verify(
|
||||||
|
o => o.EvaluatePolicy(It.IsAny<HttpContext>(), policy),
|
||||||
|
Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_HasEndpointWithDisableMetadata_SkipCors()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var corsService = Mock.Of<ICorsService>();
|
||||||
|
var mockProvider = new Mock<ICorsPolicyProvider>();
|
||||||
|
var loggerFactory = NullLoggerFactory.Instance;
|
||||||
|
mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
|
||||||
|
.Returns(Task.FromResult<CorsPolicy>(null))
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
var middleware = new CorsMiddleware(
|
||||||
|
Mock.Of<RequestDelegate>(),
|
||||||
|
corsService,
|
||||||
|
loggerFactory,
|
||||||
|
"DefaultPolicyName");
|
||||||
|
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new DisableCorsAttribute()), "Test endpoint"));
|
||||||
|
httpContext.Request.Headers.Add(CorsConstants.Origin, new[] { "http://example.com" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await middleware.Invoke(httpContext, mockProvider.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mockProvider.Verify(
|
||||||
|
o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()),
|
||||||
|
Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_HasEndpointWithMutlipleMetadata_SkipCorsBecauseOfMetadataOrder()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var corsService = Mock.Of<ICorsService>();
|
||||||
|
var mockProvider = new Mock<ICorsPolicyProvider>();
|
||||||
|
var loggerFactory = NullLoggerFactory.Instance;
|
||||||
|
mockProvider.Setup(o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()))
|
||||||
|
.Returns(Task.FromResult<CorsPolicy>(null))
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
var middleware = new CorsMiddleware(
|
||||||
|
Mock.Of<RequestDelegate>(),
|
||||||
|
corsService,
|
||||||
|
loggerFactory,
|
||||||
|
"DefaultPolicyName");
|
||||||
|
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new EnableCorsAttribute("MetadataPolicyName"), new DisableCorsAttribute()), "Test endpoint"));
|
||||||
|
httpContext.Request.Headers.Add(CorsConstants.Origin, new[] { "http://example.com" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await middleware.Invoke(httpContext, mockProvider.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mockProvider.Verify(
|
||||||
|
o => o.GetPolicyAsync(It.IsAny<HttpContext>(), It.IsAny<string>()),
|
||||||
|
Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Invoke_InvokeFlagSet()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var corsService = Mock.Of<ICorsService>();
|
||||||
|
var mockProvider = Mock.Of<ICorsPolicyProvider>();
|
||||||
|
var loggerFactory = NullLoggerFactory.Instance;
|
||||||
|
|
||||||
|
var middleware = new CorsMiddleware(
|
||||||
|
Mock.Of<RequestDelegate>(),
|
||||||
|
corsService,
|
||||||
|
loggerFactory,
|
||||||
|
"DefaultPolicyName");
|
||||||
|
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new EnableCorsAttribute("MetadataPolicyName"), new DisableCorsAttribute()), "Test endpoint"));
|
||||||
|
httpContext.Request.Headers.Add(CorsConstants.Origin, new[] { "http://example.com" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await middleware.Invoke(httpContext, mockProvider);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Contains(httpContext.Items, item => string.Equals(item.Key as string, "__CorsMiddlewareInvoked"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 15.0.26124.0
|
VisualStudioVersion = 16.0.28407.52
|
||||||
MinimumVisualStudioVersion = 15.0.26124.0
|
MinimumVisualStudioVersion = 15.0.26124.0
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebSockets", "WebSockets", "{E0D9867D-C23D-43EB-8D9C-DE0398A25432}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebSockets", "WebSockets", "{E0D9867D-C23D-43EB-8D9C-DE0398A25432}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -245,6 +245,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Crypto
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.Abstractions", "..\DataProtection\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj", "{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.Abstractions", "..\DataProtection\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj", "{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionalTests", "CORS\test\FunctionalTests\FunctionalTests.csproj", "{E025D98E-BD85-474A-98A9-E7F44F392F8E}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleDestination", "CORS\samples\SampleDestination\SampleDestination.csproj", "{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleOrigin", "CORS\samples\SampleOrigin\SampleOrigin.csproj", "{198FFE3B-0346-4856-A6C9-8752D51C4EB3}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -1335,6 +1341,42 @@ Global
|
||||||
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}.Release|x64.Build.0 = Release|Any CPU
|
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}.Release|x86.ActiveCfg = Release|Any CPU
|
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}.Release|x86.Build.0 = Release|Any CPU
|
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -1441,6 +1483,9 @@ Global
|
||||||
{3AD5B221-C718-4F14-883A-4345DC90CF9C} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
{3AD5B221-C718-4F14-883A-4345DC90CF9C} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||||
{227030D6-99AD-4C6A-AE70-1333BCBE8705} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
{227030D6-99AD-4C6A-AE70-1333BCBE8705} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||||
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||||
|
{E025D98E-BD85-474A-98A9-E7F44F392F8E} = {4967DE1B-FEC2-4C2B-8F7F-6262D67C9434}
|
||||||
|
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD} = {7CF63806-4C4F-4C48-8922-A75113975308}
|
||||||
|
{198FFE3B-0346-4856-A6C9-8752D51C4EB3} = {7CF63806-4C4F-4C48-8922-A75113975308}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {83786312-A93B-4BB4-AB06-7C6913A59AFA}
|
SolutionGuid = {83786312-A93B-4BB4-AB06-7C6913A59AFA}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue