// 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.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Web.Cors; using System.Web.Http.Cors; using System.Web.Http.Cors.Tracing; using System.Web.Http.Tracing; namespace System.Web.Http { /// /// CORS-related extension methods for . /// [EditorBrowsable(EditorBrowsableState.Never)] public static class CorsHttpConfigurationExtensions { private const string CorsEngineKey = "MS_CorsEngineKey"; private const string CorsPolicyProviderFactoryKey = "MS_CorsPolicyProviderFactoryKey"; private const string CorsEnabledKey = "MS_CorsEnabledKey"; /// /// Enables the support for CORS. /// /// The . public static void EnableCors(this HttpConfiguration httpConfiguration) { EnableCors(httpConfiguration, null, false); } /// /// Enables the support for CORS. /// /// The . /// Indicates whether upstream exceptions should be rethrown public static void EnableCors(this HttpConfiguration httpConfiguration, bool rethrowExceptions) { EnableCors(httpConfiguration, null, rethrowExceptions); } /// /// Enables the support for CORS. /// /// The . /// The default . public static void EnableCors(this HttpConfiguration httpConfiguration, ICorsPolicyProvider defaultPolicyProvider) { EnableCors(httpConfiguration, defaultPolicyProvider, false); } /// /// Enables the support for CORS. /// /// The . /// The default . /// Indicates whether upstream exceptions should be rethrown /// httpConfiguration public static void EnableCors(this HttpConfiguration httpConfiguration, ICorsPolicyProvider defaultPolicyProvider, bool rethrowExceptions) { if (httpConfiguration == null) { throw new ArgumentNullException("httpConfiguration"); } if (defaultPolicyProvider != null) { AttributeBasedPolicyProviderFactory policyProviderFactory = new AttributeBasedPolicyProviderFactory(); policyProviderFactory.DefaultPolicyProvider = defaultPolicyProvider; httpConfiguration.SetCorsPolicyProviderFactory(policyProviderFactory); } AddCorsMessageHandler(httpConfiguration, rethrowExceptions); } [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Caller owns the disposable object")] private static void AddCorsMessageHandler(this HttpConfiguration httpConfiguration, bool rethrowExceptions) { object corsEnabled; if (!httpConfiguration.Properties.TryGetValue(CorsEnabledKey, out corsEnabled)) { Action defaultInitializer = httpConfiguration.Initializer; httpConfiguration.Initializer = config => { if (!config.Properties.TryGetValue(CorsEnabledKey, out corsEnabled)) { // Execute this in the Initializer to ensure that the CorsMessageHandler is added last. config.MessageHandlers.Add(new CorsMessageHandler(config, rethrowExceptions)); ITraceWriter traceWriter = config.Services.GetTraceWriter(); if (traceWriter != null) { ICorsPolicyProviderFactory factory = config.GetCorsPolicyProviderFactory(); config.SetCorsPolicyProviderFactory(new CorsPolicyProviderFactoryTracer(factory, traceWriter)); ICorsEngine corsEngine = config.GetCorsEngine(); config.SetCorsEngine(new CorsEngineTracer(corsEngine, traceWriter)); } config.Properties[CorsEnabledKey] = true; } defaultInitializer(config); }; } } /// /// Sets the on the . /// /// The . /// The . /// /// httpConfiguration /// or /// corsEngine /// public static void SetCorsEngine(this HttpConfiguration httpConfiguration, ICorsEngine corsEngine) { if (httpConfiguration == null) { throw new ArgumentNullException("httpConfiguration"); } if (corsEngine == null) { throw new ArgumentNullException("corsEngine"); } httpConfiguration.Properties[CorsEngineKey] = corsEngine; } /// /// Gets the from the . /// /// The . /// The . /// httpConfiguration public static ICorsEngine GetCorsEngine(this HttpConfiguration httpConfiguration) { if (httpConfiguration == null) { throw new ArgumentNullException("httpConfiguration"); } return (ICorsEngine)httpConfiguration.Properties.GetOrAdd(CorsEngineKey, k => new CorsEngine()); } /// /// Sets the on the . /// /// The . /// The . /// /// httpConfiguration /// or /// corsPolicyProviderFactory /// public static void SetCorsPolicyProviderFactory(this HttpConfiguration httpConfiguration, ICorsPolicyProviderFactory corsPolicyProviderFactory) { if (httpConfiguration == null) { throw new ArgumentNullException("httpConfiguration"); } if (corsPolicyProviderFactory == null) { throw new ArgumentNullException("corsPolicyProviderFactory"); } httpConfiguration.Properties[CorsPolicyProviderFactoryKey] = corsPolicyProviderFactory; } /// /// Gets the from the . /// /// The . /// The . /// httpConfiguration public static ICorsPolicyProviderFactory GetCorsPolicyProviderFactory(this HttpConfiguration httpConfiguration) { if (httpConfiguration == null) { throw new ArgumentNullException("httpConfiguration"); } return (ICorsPolicyProviderFactory)httpConfiguration.Properties.GetOrAdd(CorsPolicyProviderFactoryKey, k => new AttributeBasedPolicyProviderFactory()); } } }