From 4a61dfec6d8f28e5a5e85c7ea80c941b4a665aa0 Mon Sep 17 00:00:00 2001 From: ryanbrandenburg Date: Fri, 13 Nov 2015 14:35:48 -0800 Subject: [PATCH] * Make HttpMethodConstraint case insensitive --- .../ActionConstraints/HttpMethodConstraint.cs | 4 +- .../HttpMethodConstraintTest.cs | 89 +++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 test/Microsoft.AspNet.Mvc.Core.Test/HttpMethodConstraintTest.cs diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionConstraints/HttpMethodConstraint.cs b/src/Microsoft.AspNet.Mvc.Core/ActionConstraints/HttpMethodConstraint.cs index 3dc9143aca..bb7b400471 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionConstraints/HttpMethodConstraint.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionConstraints/HttpMethodConstraint.cs @@ -76,7 +76,7 @@ namespace Microsoft.AspNet.Mvc.ActionConstraints if (string.Equals( request.Method, PreflightHttpMethod, - StringComparison.Ordinal) && + StringComparison.OrdinalIgnoreCase) && !StringValues.IsNullOrEmpty(accessControlRequestMethod)) { method = accessControlRequestMethod; @@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.ActionConstraints for (var i = 0; i < _httpMethods.Count; i++) { var supportedMethod = _httpMethods[i]; - if (string.Equals(supportedMethod, method, StringComparison.Ordinal)) + if (string.Equals(supportedMethod, method, StringComparison.OrdinalIgnoreCase)) { return true; } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/HttpMethodConstraintTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/HttpMethodConstraintTest.cs new file mode 100644 index 0000000000..5868ee3e69 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Core.Test/HttpMethodConstraintTest.cs @@ -0,0 +1,89 @@ +// 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.Collections.Generic; +using Microsoft.AspNet.Http.Internal; +using Microsoft.AspNet.Mvc.Abstractions; +using Microsoft.AspNet.Mvc.ActionConstraints; +using Microsoft.AspNet.Routing; +using Microsoft.Extensions.Primitives; +using Xunit; + +namespace Microsoft.AspNet.Mvc +{ + public class HttpMethodConstraintTest + { + public static TheoryData AcceptCaseInsensitiveData = + new TheoryData, string> + { + { new string[] { "get", "Get", "GET", "GEt"}, "gEt" }, + { new string[] { "POST", "PoSt", "GEt"}, "GET" }, + { new string[] { "get" }, "get" }, + { new string[] { "post" }, "POST" }, + { new string[] { "gEt" }, "get" }, + { new string[] { "get", "PoST" }, "pOSt" } + }; + + [Theory] + [MemberData(nameof(AcceptCaseInsensitiveData))] + public void HttpMethodConstraint_Accept_Preflight_CaseInsensitive(IEnumerable httpMethods, string accessControlMethod) + { + // Arrange + var constraint = new HttpMethodConstraint(httpMethods); + var context = CreateActionConstraintContext(constraint); + context.RouteContext = CreateRouteContext("oPtIoNs", accessControlMethod); + + // Act + var result = constraint.Accept(context); + + // Assert + Assert.True(result, "Request should have been accepted."); + } + + [Theory] + [MemberData(nameof(AcceptCaseInsensitiveData))] + public void HttpMethodConstraint_Accept_CaseInsensitive(IEnumerable httpMethods, string expectedMethod) + { + // Arrange + var constraint = new HttpMethodConstraint(httpMethods); + var context = CreateActionConstraintContext(constraint); + context.RouteContext = CreateRouteContext(expectedMethod); + + // Act + var result = constraint.Accept(context); + + // Assert + Assert.True(result, "Request should have been accepted."); + } + + private static ActionConstraintContext CreateActionConstraintContext(HttpMethodConstraint constraint) + { + var context = new ActionConstraintContext(); + + var actionSelectorCandidate = new ActionSelectorCandidate(new ActionDescriptor(), new List { constraint }); + + context.Candidates = new List { actionSelectorCandidate }; + context.CurrentCandidate = context.Candidates[0]; + + return context; + } + + private static RouteContext CreateRouteContext(string requestedMethod, string accessControlMethod = null) + { + var httpContext = new DefaultHttpContext(); + + httpContext.Request.Method = requestedMethod; + + if (accessControlMethod != null) + { + httpContext.Request.Headers.Add("Origin", StringValues.Empty); + httpContext.Request.Headers.Add("Access-Control-Request-Method", accessControlMethod); + } + + var routeContext = new RouteContext(httpContext); + routeContext.RouteData = new RouteData(); + + return routeContext; + } + } +}