[Fixes #77] Make HTTP method match as case-insensitive

This commit is contained in:
Kiran Challa 2016-08-03 09:28:08 -07:00
parent b5abd73e34
commit 15b66cec1f
4 changed files with 112 additions and 11 deletions

View File

@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
if (string.Equals( if (string.Equals(
context.Request.Method, context.Request.Method,
CorsConstants.PreflightHttpMethod, CorsConstants.PreflightHttpMethod,
StringComparison.Ordinal) && StringComparison.OrdinalIgnoreCase) &&
!StringValues.IsNullOrEmpty(accessControlRequestMethod)) !StringValues.IsNullOrEmpty(accessControlRequestMethod))
{ {
// Since there is a policy which was identified, // Since there is a policy which was identified,

View File

@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var corsResult = new CorsResult(); var corsResult = new CorsResult();
var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod]; var accessControlRequestMethod = context.Request.Headers[CorsConstants.AccessControlRequestMethod];
if (string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.Ordinal) && if (string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase) &&
!StringValues.IsNullOrEmpty(accessControlRequestMethod)) !StringValues.IsNullOrEmpty(accessControlRequestMethod))
{ {
EvaluatePreflightRequest(context, policy, corsResult); EvaluatePreflightRequest(context, policy, corsResult);
@ -109,9 +109,23 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
var requestHeaders = var requestHeaders =
context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders); context.Request.Headers.GetCommaSeparatedValues(CorsConstants.AccessControlRequestHeaders);
if (!policy.AllowAnyMethod && !policy.Methods.Contains(accessControlRequestMethod)) if (!policy.AllowAnyMethod)
{ {
return; var found = false;
for (var i = 0; i < policy.Methods.Count; i++)
{
var method = policy.Methods[i];
if (string.Equals(method, accessControlRequestMethod, StringComparison.OrdinalIgnoreCase))
{
found = true;
break;
}
}
if (!found)
{
return;
}
} }
if (!policy.AllowAnyHeader && if (!policy.AllowAnyHeader &&

View File

@ -16,6 +16,41 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
{ {
public class CorsMiddlewareTests public class CorsMiddlewareTests
{ {
[Theory]
[InlineData("PuT")]
[InlineData("PUT")]
public async Task CorsRequest_MatchesPolicy_OnCaseInsensitiveAccessControlRequestMethod(string accessControlRequestMethod)
{
// Arrange
var hostBuilder = new WebHostBuilder()
.Configure(app =>
{
app.UseCors(builder =>
builder.WithOrigins("http://localhost:5001")
.WithMethods("PUT"));
app.Run(async context =>
{
await context.Response.WriteAsync("Cross origin response");
});
})
.ConfigureServices(services => services.AddCors());
using (var server = new TestServer(hostBuilder))
{
// Act
// Actual request.
var response = await server.CreateRequest("/")
.AddHeader(CorsConstants.Origin, "http://localhost:5001")
.SendAsync(accessControlRequestMethod);
// Assert
response.EnsureSuccessStatusCode();
Assert.Equal(1, response.Headers.Count());
Assert.Equal("Cross origin response", await response.Content.ReadAsStringAsync());
Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
}
}
[Fact] [Fact]
public async Task CorsRequest_MatchPolicy_SetsResponseHeaders() public async Task CorsRequest_MatchPolicy_SetsResponseHeaders()
{ {
@ -52,6 +87,48 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
} }
} }
[Theory]
[InlineData("OpTions")]
[InlineData("OPTIONS")]
public async Task PreFlight_MatchesPolicy_OnCaseInsensitiveOptionsMethod(string preflightMethod)
{
// Arrange
var policy = new CorsPolicy();
policy.Origins.Add("http://localhost:5001");
policy.Methods.Add("PUT");
var hostBuilder = new WebHostBuilder()
.Configure(app =>
{
app.UseCors("customPolicy");
app.Run(async context =>
{
await context.Response.WriteAsync("Cross origin response");
});
})
.ConfigureServices(services =>
{
services.AddCors(options =>
{
options.AddPolicy("customPolicy", policy);
});
});
using (var server = new TestServer(hostBuilder))
{
// Act
// Preflight request.
var response = await server.CreateRequest("/")
.AddHeader(CorsConstants.Origin, "http://localhost:5001")
.SendAsync(preflightMethod);
// Assert
response.EnsureSuccessStatusCode();
Assert.Equal(1, response.Headers.Count());
Assert.Equal("http://localhost:5001", response.Headers.GetValues(CorsConstants.AccessControlAllowOrigin).FirstOrDefault());
}
}
[Fact] [Fact]
public async Task PreFlight_MatchesPolicy_SetsResponseHeaders() public async Task PreFlight_MatchesPolicy_SetsResponseHeaders()
{ {

View File

@ -227,12 +227,17 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
Assert.Contains("PUT", result.AllowedMethods); Assert.Contains("PUT", result.AllowedMethods);
} }
[Fact] [Theory]
public void EvaluatePolicy_PreflightRequest_OriginAllowed_ReturnsOrigin() [InlineData("OpTions")]
[InlineData("OPTIONS")]
public void EvaluatePolicy_CaseInsensitivePreflightRequest_OriginAllowed_ReturnsOrigin(string preflightMethod)
{ {
// Arrange // Arrange
var corsService = new CorsService(new TestCorsOptions()); var corsService = new CorsService(new TestCorsOptions());
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var requestContext = GetHttpContext(
method: preflightMethod,
origin: "http://example.com",
accessControlRequestMethod: "PUT");
var policy = new CorsPolicy(); var policy = new CorsPolicy();
policy.Origins.Add(CorsConstants.AnyOrigin); policy.Origins.Add(CorsConstants.AnyOrigin);
policy.Origins.Add("http://example.com"); policy.Origins.Add("http://example.com");
@ -323,12 +328,17 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
Assert.Contains("GET", result.AllowedMethods); Assert.Contains("GET", result.AllowedMethods);
} }
[Fact] [Theory]
public void EvaluatePolicy_PreflightRequest_ListedMethod_ReturnsSubsetOfListedMethods() [InlineData("Put")]
[InlineData("PUT")]
public void EvaluatePolicy_CaseInsensitivePreflightRequest_ListedMethod_ReturnsSubsetOfListedMethods(string method)
{ {
// Arrange // Arrange
var corsService = new CorsService(new TestCorsOptions()); var corsService = new CorsService(new TestCorsOptions());
var requestContext = GetHttpContext(method: "OPTIONS", origin: "http://example.com", accessControlRequestMethod: "PUT"); var requestContext = GetHttpContext(
method: "OPTIONS",
origin: "http://example.com",
accessControlRequestMethod: method);
var policy = new CorsPolicy(); var policy = new CorsPolicy();
policy.Origins.Add(CorsConstants.AnyOrigin); policy.Origins.Add(CorsConstants.AnyOrigin);
policy.Methods.Add("PUT"); policy.Methods.Add("PUT");
@ -339,7 +349,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Assert // Assert
Assert.Equal(1, result.AllowedMethods.Count); Assert.Equal(1, result.AllowedMethods.Count);
Assert.Contains("PUT", result.AllowedMethods); Assert.Contains(method, result.AllowedMethods);
} }
[Fact] [Fact]