[Fixes #77] Make HTTP method match as case-insensitive
This commit is contained in:
parent
b5abd73e34
commit
15b66cec1f
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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 &&
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue