// 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 System.Collections.ObjectModel; using System.Linq; using Microsoft.Framework.Internal; using Microsoft.Framework.Primitives; namespace Microsoft.AspNet.Mvc.ActionConstraints { public class HttpMethodConstraint : IActionConstraint { public static readonly int HttpMethodConstraintOrder = 100; private readonly IReadOnlyList _methods; private readonly string OriginHeader = "Origin"; private readonly string AccessControlRequestMethod = "Access-Control-Request-Method"; private readonly string PreflightHttpMethod = "OPTIONS"; // Empty collection means any method will be accepted. public HttpMethodConstraint([NotNull] IEnumerable httpMethods) { var methods = new List(); foreach (var method in httpMethods) { if (string.IsNullOrEmpty(method)) { throw new ArgumentException("httpMethod cannot be null or empty"); } methods.Add(method); } _methods = new ReadOnlyCollection(methods); } public IEnumerable HttpMethods { get { return _methods; } } public int Order { get { return HttpMethodConstraintOrder; } } public bool Accept([NotNull] ActionConstraintContext context) { if (_methods.Count == 0) { return true; } var request = context.RouteContext.HttpContext.Request; var method = request.Method; if (request.Headers.ContainsKey(OriginHeader)) { // Update the http method if it is preflight request. var accessControlRequestMethod = request.Headers[AccessControlRequestMethod]; if (string.Equals( request.Method, PreflightHttpMethod, StringComparison.Ordinal) && !StringValues.IsNullOrEmpty(accessControlRequestMethod)) { method = accessControlRequestMethod; } } return (HttpMethods.Any(m => m.Equals(method, StringComparison.Ordinal))); } } }