Add EndpointMetadata to ActionDescriptor and hookup CORS (#8158)
This commit is contained in:
parent
556880872d
commit
c01c7075be
|
|
@ -16,87 +16,87 @@
|
||||||
<BenchmarksOnlyMySqlConnectorPackageVersion>0.42.1</BenchmarksOnlyMySqlConnectorPackageVersion>
|
<BenchmarksOnlyMySqlConnectorPackageVersion>0.42.1</BenchmarksOnlyMySqlConnectorPackageVersion>
|
||||||
<BenchmarksOnlyNpgsqlEntityFrameworkCorePostgreSQLPackageVersion>2.1.0</BenchmarksOnlyNpgsqlEntityFrameworkCorePostgreSQLPackageVersion>
|
<BenchmarksOnlyNpgsqlEntityFrameworkCorePostgreSQLPackageVersion>2.1.0</BenchmarksOnlyNpgsqlEntityFrameworkCorePostgreSQLPackageVersion>
|
||||||
<BenchmarksOnlyPomeloEntityFrameworkCoreMySqlPackageVersion>2.1.0-rc1-final</BenchmarksOnlyPomeloEntityFrameworkCoreMySqlPackageVersion>
|
<BenchmarksOnlyPomeloEntityFrameworkCoreMySqlPackageVersion>2.1.0-rc1-final</BenchmarksOnlyPomeloEntityFrameworkCoreMySqlPackageVersion>
|
||||||
<InternalAspNetCoreAnalyzersPackageVersion>2.2.0-preview1-34784</InternalAspNetCoreAnalyzersPackageVersion>
|
<InternalAspNetCoreAnalyzersPackageVersion>2.2.0-preview1-34816</InternalAspNetCoreAnalyzersPackageVersion>
|
||||||
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview1-17099</InternalAspNetCoreSdkPackageVersion>
|
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview1-17099</InternalAspNetCoreSdkPackageVersion>
|
||||||
<MicrosoftAspNetCoreAllPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreAllPackageVersion>
|
<MicrosoftAspNetCoreAllPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreAllPackageVersion>
|
||||||
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
|
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
|
||||||
<MicrosoftAspNetCoreAntiforgeryPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreAntiforgeryPackageVersion>
|
<MicrosoftAspNetCoreAntiforgeryPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreAntiforgeryPackageVersion>
|
||||||
<MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>
|
<MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreAuthenticationCookiesPackageVersion>
|
||||||
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
|
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
|
||||||
<MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>
|
<MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion>
|
||||||
<MicrosoftAspNetCoreAuthenticationPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreAuthenticationPackageVersion>
|
<MicrosoftAspNetCoreAuthenticationPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreAuthenticationPackageVersion>
|
||||||
<MicrosoftAspNetCoreAuthorizationPolicyPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreAuthorizationPolicyPackageVersion>
|
<MicrosoftAspNetCoreAuthorizationPolicyPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreAuthorizationPolicyPackageVersion>
|
||||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||||
<MicrosoftAspNetCoreChunkingCookieManagerSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreChunkingCookieManagerSourcesPackageVersion>
|
<MicrosoftAspNetCoreChunkingCookieManagerSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreChunkingCookieManagerSourcesPackageVersion>
|
||||||
<MicrosoftAspNetCoreCookiePolicyPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreCookiePolicyPackageVersion>
|
<MicrosoftAspNetCoreCookiePolicyPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreCookiePolicyPackageVersion>
|
||||||
<MicrosoftAspNetCoreCorsPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreCorsPackageVersion>
|
<MicrosoftAspNetCoreCorsPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreCorsPackageVersion>
|
||||||
<MicrosoftAspNetCoreDiagnosticsAbstractionsPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreDiagnosticsAbstractionsPackageVersion>
|
<MicrosoftAspNetCoreDiagnosticsAbstractionsPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreDiagnosticsAbstractionsPackageVersion>
|
||||||
<MicrosoftAspNetCoreDiagnosticsPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreDiagnosticsPackageVersion>
|
<MicrosoftAspNetCoreDiagnosticsPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreDiagnosticsPackageVersion>
|
||||||
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
|
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
|
||||||
<MicrosoftAspNetCoreHostingPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreHostingPackageVersion>
|
<MicrosoftAspNetCoreHostingPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreHostingPackageVersion>
|
||||||
<MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>
|
<MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>
|
||||||
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
|
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
|
||||||
<MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreHttpPackageVersion>
|
<MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreHttpPackageVersion>
|
||||||
<MicrosoftAspNetCoreJsonPatchPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreJsonPatchPackageVersion>
|
<MicrosoftAspNetCoreJsonPatchPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreJsonPatchPackageVersion>
|
||||||
<MicrosoftAspNetCoreLocalizationPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreLocalizationPackageVersion>
|
<MicrosoftAspNetCoreLocalizationPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreLocalizationPackageVersion>
|
||||||
<MicrosoftAspNetCoreLocalizationRoutingPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreLocalizationRoutingPackageVersion>
|
<MicrosoftAspNetCoreLocalizationRoutingPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreLocalizationRoutingPackageVersion>
|
||||||
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
|
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
|
||||||
<MicrosoftAspNetCoreRangeHelperSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreRangeHelperSourcesPackageVersion>
|
<MicrosoftAspNetCoreRangeHelperSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreRangeHelperSourcesPackageVersion>
|
||||||
<MicrosoftAspNetCoreRazorDesignPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreRazorDesignPackageVersion>
|
<MicrosoftAspNetCoreRazorDesignPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreRazorDesignPackageVersion>
|
||||||
<MicrosoftAspNetCoreRazorLanguagePackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreRazorLanguagePackageVersion>
|
<MicrosoftAspNetCoreRazorLanguagePackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreRazorLanguagePackageVersion>
|
||||||
<MicrosoftAspNetCoreRazorRuntimePackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreRazorRuntimePackageVersion>
|
<MicrosoftAspNetCoreRazorRuntimePackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreRazorRuntimePackageVersion>
|
||||||
<MicrosoftAspNetCoreRazorTagHelpersTestingSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreRazorTagHelpersTestingSourcesPackageVersion>
|
<MicrosoftAspNetCoreRazorTagHelpersTestingSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreRazorTagHelpersTestingSourcesPackageVersion>
|
||||||
<MicrosoftAspNetCoreResponseCachingAbstractionsPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreResponseCachingAbstractionsPackageVersion>
|
<MicrosoftAspNetCoreResponseCachingAbstractionsPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreResponseCachingAbstractionsPackageVersion>
|
||||||
<MicrosoftAspNetCoreResponseCachingPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreResponseCachingPackageVersion>
|
<MicrosoftAspNetCoreResponseCachingPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreResponseCachingPackageVersion>
|
||||||
<MicrosoftAspNetCoreRoutingAbstractionsPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreRoutingAbstractionsPackageVersion>
|
<MicrosoftAspNetCoreRoutingAbstractionsPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreRoutingAbstractionsPackageVersion>
|
||||||
<MicrosoftAspNetCoreRoutingPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreRoutingPackageVersion>
|
<MicrosoftAspNetCoreRoutingPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreRoutingPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
||||||
<MicrosoftAspNetCoreSessionPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreSessionPackageVersion>
|
<MicrosoftAspNetCoreSessionPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreSessionPackageVersion>
|
||||||
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreStaticFilesPackageVersion>
|
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreStaticFilesPackageVersion>
|
||||||
<MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreTestHostPackageVersion>
|
<MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreTestHostPackageVersion>
|
||||||
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreTestingPackageVersion>
|
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreTestingPackageVersion>
|
||||||
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview1-34784</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview1-34816</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
||||||
<MicrosoftAspNetWebApiClientPackageVersion>5.2.6</MicrosoftAspNetWebApiClientPackageVersion>
|
<MicrosoftAspNetWebApiClientPackageVersion>5.2.6</MicrosoftAspNetWebApiClientPackageVersion>
|
||||||
<MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpPackageVersion>
|
<MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpPackageVersion>
|
||||||
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
|
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
|
||||||
<MicrosoftCodeAnalysisRazorPackageVersion>2.2.0-preview1-34784</MicrosoftCodeAnalysisRazorPackageVersion>
|
<MicrosoftCodeAnalysisRazorPackageVersion>2.2.0-preview1-34816</MicrosoftCodeAnalysisRazorPackageVersion>
|
||||||
<MicrosoftDiaSymReaderNativePackageVersion>1.7.0</MicrosoftDiaSymReaderNativePackageVersion>
|
<MicrosoftDiaSymReaderNativePackageVersion>1.7.0</MicrosoftDiaSymReaderNativePackageVersion>
|
||||||
<MicrosoftExtensionsCachingMemoryPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsCachingMemoryPackageVersion>
|
<MicrosoftExtensionsCachingMemoryPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||||
<MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>
|
<MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsConfigurationPackageVersion>
|
<MicrosoftExtensionsConfigurationPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsConfigurationPackageVersion>
|
||||||
<MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>
|
<MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>
|
||||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||||
<MicrosoftExtensionsDependencyModelPackageVersion>2.1.0</MicrosoftExtensionsDependencyModelPackageVersion>
|
<MicrosoftExtensionsDependencyModelPackageVersion>2.1.0</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||||
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
|
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
|
||||||
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsFileProvidersCompositePackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
<MicrosoftExtensionsFileProvidersCompositePackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
||||||
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
|
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
|
||||||
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
||||||
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
|
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsLocalizationPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsLocalizationPackageVersion>
|
<MicrosoftExtensionsLocalizationPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsLocalizationPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsLoggingConsolePackageVersion>
|
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||||
<MicrosoftExtensionsLoggingDebugPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsLoggingDebugPackageVersion>
|
<MicrosoftExtensionsLoggingDebugPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsLoggingPackageVersion>
|
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsLoggingPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsLoggingTestingPackageVersion>
|
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||||
<MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>
|
<MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsOptionsPackageVersion>
|
<MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsOptionsPackageVersion>
|
||||||
<MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>
|
<MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsPrimitivesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsPrimitivesPackageVersion>
|
<MicrosoftExtensionsPrimitivesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsPrimitivesPackageVersion>
|
||||||
<MicrosoftExtensionsPropertyActivatorSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsPropertyActivatorSourcesPackageVersion>
|
<MicrosoftExtensionsPropertyActivatorSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsPropertyActivatorSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsPropertyHelperSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsPropertyHelperSourcesPackageVersion>
|
<MicrosoftExtensionsPropertyHelperSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsPropertyHelperSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
|
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
|
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsValueStopwatchSourcesPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
|
<MicrosoftExtensionsValueStopwatchSourcesPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
|
||||||
<MicrosoftExtensionsWebEncodersPackageVersion>2.2.0-preview1-34784</MicrosoftExtensionsWebEncodersPackageVersion>
|
<MicrosoftExtensionsWebEncodersPackageVersion>2.2.0-preview1-34816</MicrosoftExtensionsWebEncodersPackageVersion>
|
||||||
<MicrosoftNETCoreApp20PackageVersion>2.0.9</MicrosoftNETCoreApp20PackageVersion>
|
<MicrosoftNETCoreApp20PackageVersion>2.0.9</MicrosoftNETCoreApp20PackageVersion>
|
||||||
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
|
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
|
||||||
<MicrosoftNETCoreApp22PackageVersion>2.2.0-preview1-26618-02</MicrosoftNETCoreApp22PackageVersion>
|
<MicrosoftNETCoreApp22PackageVersion>2.2.0-preview1-26618-02</MicrosoftNETCoreApp22PackageVersion>
|
||||||
<MicrosoftNetHttpHeadersPackageVersion>2.2.0-preview1-34784</MicrosoftNetHttpHeadersPackageVersion>
|
<MicrosoftNetHttpHeadersPackageVersion>2.2.0-preview1-34816</MicrosoftNetHttpHeadersPackageVersion>
|
||||||
<MicrosoftNETSdkRazorPackageVersion>2.2.0-preview1-34784</MicrosoftNETSdkRazorPackageVersion>
|
<MicrosoftNETSdkRazorPackageVersion>2.2.0-preview1-34816</MicrosoftNETSdkRazorPackageVersion>
|
||||||
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
|
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
|
||||||
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
||||||
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IList<IActionConstraintMetadata> ActionConstraints { get; set; }
|
public IList<IActionConstraintMetadata> ActionConstraints { get; set; }
|
||||||
|
|
||||||
|
public IList<object> EndpointMetadata { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The set of parameters associated with this action.
|
/// The set of parameters associated with this action.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
||||||
public SelectorModel()
|
public SelectorModel()
|
||||||
{
|
{
|
||||||
ActionConstraints = new List<IActionConstraintMetadata>();
|
ActionConstraints = new List<IActionConstraintMetadata>();
|
||||||
|
EndpointMetadata = new List<object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelectorModel(SelectorModel other)
|
public SelectorModel(SelectorModel other)
|
||||||
|
|
@ -22,6 +23,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionConstraints = new List<IActionConstraintMetadata>(other.ActionConstraints);
|
ActionConstraints = new List<IActionConstraintMetadata>(other.ActionConstraints);
|
||||||
|
EndpointMetadata = new List<object>(other.EndpointMetadata);
|
||||||
|
|
||||||
if (other.AttributeRouteModel != null)
|
if (other.AttributeRouteModel != null)
|
||||||
{
|
{
|
||||||
|
|
@ -32,5 +34,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
||||||
public AttributeRouteModel AttributeRouteModel { get; set; }
|
public AttributeRouteModel AttributeRouteModel { get; set; }
|
||||||
|
|
||||||
public IList<IActionConstraintMetadata> ActionConstraints { get; }
|
public IList<IActionConstraintMetadata> ActionConstraints { get; }
|
||||||
|
|
||||||
|
public IList<object> EndpointMetadata { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.Routing;
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
|
using Microsoft.AspNetCore.Routing.Metadata;
|
||||||
using Resources = Microsoft.AspNetCore.Mvc.Core.Resources;
|
using Resources = Microsoft.AspNetCore.Mvc.Core.Resources;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
|
|
@ -163,6 +164,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
AddActionConstraints(actionDescriptor, actionSelector, controllerConstraints);
|
AddActionConstraints(actionDescriptor, actionSelector, controllerConstraints);
|
||||||
|
|
||||||
|
// REVIEW: Need to get metadata from controller
|
||||||
|
actionDescriptor.EndpointMetadata = actionSelector.EndpointMetadata.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionDescriptors;
|
return actionDescriptors;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNetCore.Mvc.Routing;
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
|
using Microsoft.AspNetCore.Routing.Metadata;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
|
@ -641,6 +642,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
AddRange(selectorModel.ActionConstraints, attributes.OfType<IActionConstraintMetadata>());
|
AddRange(selectorModel.ActionConstraints, attributes.OfType<IActionConstraintMetadata>());
|
||||||
|
AddRange(selectorModel.EndpointMetadata, attributes);
|
||||||
|
|
||||||
// Simple case, all HTTP method attributes apply
|
// Simple case, all HTTP method attributes apply
|
||||||
var httpMethods = attributes
|
var httpMethods = attributes
|
||||||
|
|
@ -652,6 +654,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
if (httpMethods.Length > 0)
|
if (httpMethods.Length > 0)
|
||||||
{
|
{
|
||||||
selectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(httpMethods));
|
selectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(httpMethods));
|
||||||
|
selectorModel.EndpointMetadata.Add(new HttpMethodMetadata(httpMethods));
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectorModel;
|
return selectorModel;
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,18 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
||||||
using Microsoft.AspNetCore.Routing.Matchers;
|
using Microsoft.AspNetCore.Routing.Matchers;
|
||||||
|
using Microsoft.AspNetCore.Routing.Metadata;
|
||||||
using Microsoft.AspNetCore.Routing.Patterns;
|
using Microsoft.AspNetCore.Routing.Patterns;
|
||||||
using Microsoft.AspNetCore.Routing.Template;
|
using Microsoft.AspNetCore.Routing.Template;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
@ -316,6 +319,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
metadata.Add(source);
|
metadata.Add(source);
|
||||||
metadata.Add(action);
|
metadata.Add(action);
|
||||||
|
|
||||||
|
if (action.EndpointMetadata != null)
|
||||||
|
{
|
||||||
|
metadata.AddRange(action.EndpointMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(routeName))
|
if (!string.IsNullOrEmpty(routeName))
|
||||||
{
|
{
|
||||||
metadata.Add(new RouteNameMetadata(routeName));
|
metadata.Add(new RouteNameMetadata(routeName));
|
||||||
|
|
@ -334,11 +342,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
// Currently they need to implement IActionConstraintMetadata
|
// Currently they need to implement IActionConstraintMetadata
|
||||||
foreach (var actionConstraint in action.ActionConstraints)
|
foreach (var actionConstraint in action.ActionConstraints)
|
||||||
{
|
{
|
||||||
if (actionConstraint is HttpMethodActionConstraint httpMethodActionConstraint)
|
if (actionConstraint is IEndpointConstraintMetadata)
|
||||||
{
|
|
||||||
metadata.Add(new HttpMethodEndpointConstraint(httpMethodActionConstraint.HttpMethods));
|
|
||||||
}
|
|
||||||
else if (actionConstraint is IEndpointConstraintMetadata)
|
|
||||||
{
|
{
|
||||||
// The constraint might have been added earlier, e.g. it is also a filter descriptor
|
// The constraint might have been added earlier, e.g. it is also a filter descriptor
|
||||||
if (!metadata.Contains(actionConstraint))
|
if (!metadata.Contains(actionConstraint))
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ using System.Linq;
|
||||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||||
using Microsoft.AspNetCore.Mvc.Internal;
|
using Microsoft.AspNetCore.Mvc.Internal;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.AspNetCore.Routing.Metadata;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -67,17 +67,18 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
|
|
||||||
if (isCorsEnabledGlobally || corsOnController || corsOnAction)
|
if (isCorsEnabledGlobally || corsOnController || corsOnAction)
|
||||||
{
|
{
|
||||||
UpdateHttpMethodActionConstraint(actionModel);
|
UpdateActionToAcceptCorsPreflight(actionModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateHttpMethodActionConstraint(ActionModel actionModel)
|
private static void UpdateActionToAcceptCorsPreflight(ActionModel actionModel)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < actionModel.Selectors.Count; i++)
|
for (var i = 0; i < actionModel.Selectors.Count; i++)
|
||||||
{
|
{
|
||||||
var selectorModel = actionModel.Selectors[i];
|
var selectorModel = actionModel.Selectors[i];
|
||||||
|
|
||||||
for (var j = 0; j < selectorModel.ActionConstraints.Count; j++)
|
for (var j = 0; j < selectorModel.ActionConstraints.Count; j++)
|
||||||
{
|
{
|
||||||
if (selectorModel.ActionConstraints[j] is HttpMethodActionConstraint httpConstraint)
|
if (selectorModel.ActionConstraints[j] is HttpMethodActionConstraint httpConstraint)
|
||||||
|
|
@ -85,6 +86,14 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
selectorModel.ActionConstraints[j] = new CorsHttpMethodActionConstraint(httpConstraint);
|
selectorModel.ActionConstraints[j] = new CorsHttpMethodActionConstraint(httpConstraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < selectorModel.EndpointMetadata.Count; j++)
|
||||||
|
{
|
||||||
|
if (selectorModel.EndpointMetadata[j] is HttpMethodMetadata httpMethodMetadata)
|
||||||
|
{
|
||||||
|
selectorModel.EndpointMetadata[j] = new HttpMethodMetadata(httpMethodMetadata.HttpMethods, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Mvc.Controllers;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNetCore.Mvc.Routing;
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
|
using Microsoft.AspNetCore.Routing.Metadata;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -251,6 +252,62 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
Assert.Equal(nameof(ConventionallyRoutedController.ConventionalAction), actionConstraint.Value);
|
Assert.Equal(nameof(ConventionallyRoutedController.ConventionalAction), actionConstraint.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetDescriptors_ActionWithHttpMethods_AddedToEndpointMetadata()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var descriptors = GetDescriptors(
|
||||||
|
typeof(AttributeRoutedController).GetTypeInfo());
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var action = Assert.Single(descriptors);
|
||||||
|
|
||||||
|
Assert.NotNull(action.EndpointMetadata);
|
||||||
|
|
||||||
|
Assert.Collection(action.EndpointMetadata,
|
||||||
|
metadata => Assert.IsType<HttpGetAttribute>(metadata),
|
||||||
|
metadata =>
|
||||||
|
{
|
||||||
|
var httpMethodMetadata = Assert.IsType<HttpMethodMetadata>(metadata);
|
||||||
|
|
||||||
|
Assert.False(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
|
Assert.Equal("GET", Assert.Single(httpMethodMetadata.HttpMethods));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetDescriptors_ActionWithMultipleHttpMethods_SingleHttpMethodMetadata()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var descriptors = GetDescriptors(
|
||||||
|
typeof(NonDuplicatedAttributeRouteController).GetTypeInfo());
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var actions = descriptors
|
||||||
|
.OfType<ControllerActionDescriptor>()
|
||||||
|
.Where(d => d.ActionName == nameof(NonDuplicatedAttributeRouteController.DifferentHttpMethods));
|
||||||
|
|
||||||
|
Assert.Collection(actions,
|
||||||
|
InspectElement("GET"),
|
||||||
|
InspectElement("POST"),
|
||||||
|
InspectElement("PUT"),
|
||||||
|
InspectElement("PATCH"),
|
||||||
|
InspectElement("DELETE"));
|
||||||
|
|
||||||
|
Action<ControllerActionDescriptor> InspectElement(string httpMethod)
|
||||||
|
{
|
||||||
|
return (descriptor) =>
|
||||||
|
{
|
||||||
|
var httpMethodAttribute = Assert.Single(descriptor.EndpointMetadata.OfType<HttpMethodAttribute>());
|
||||||
|
Assert.Equal(httpMethod, httpMethodAttribute.HttpMethods.Single(), ignoreCase: true);
|
||||||
|
|
||||||
|
var httpMethodMetadata = Assert.Single(descriptor.EndpointMetadata.OfType<IHttpMethodMetadata>());
|
||||||
|
Assert.Equal(httpMethod, httpMethodMetadata.HttpMethods.Single(), ignoreCase: true);
|
||||||
|
Assert.False(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetDescriptors_AddsControllerAndActionDefaults_ToAttributeRoutedActions()
|
public void GetDescriptors_AddsControllerAndActionDefaults_ToAttributeRoutedActions()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
|
|
@ -10,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.Internal;
|
using Microsoft.AspNetCore.Mvc.Internal;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
|
using Microsoft.AspNetCore.Routing.Metadata;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
@ -36,6 +38,8 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.True(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -55,10 +59,12 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.True(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateControllerModel_CustomCorsFilter_ReplacesHttpConstraints()
|
public void CreateControllerModel_CustomCorsFilter_EnablesCorsPreflight()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var corsProvider = new CorsApplicationModelProvider();
|
var corsProvider = new CorsApplicationModelProvider();
|
||||||
|
|
@ -73,6 +79,8 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.True(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -92,6 +100,8 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.True(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -111,10 +121,12 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.True(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void BuildActionModel_CustomCorsAuthorizationFilterOnAction_ReplacesHttpConstraints()
|
public void BuildActionModel_CustomCorsAuthorizationFilterOnAction_EnablesCorsPreflight()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var corsProvider = new CorsApplicationModelProvider();
|
var corsProvider = new CorsApplicationModelProvider();
|
||||||
|
|
@ -129,10 +141,12 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.True(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateControllerModel_EnableCorsGloballyReplacesHttpMethodConstraints()
|
public void CreateControllerModel_EnableCorsGloballyEnablesCorsPreflight()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var corsProvider = new CorsApplicationModelProvider();
|
var corsProvider = new CorsApplicationModelProvider();
|
||||||
|
|
@ -150,10 +164,12 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.True(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateControllerModel_DisableCorsGloballyReplacesHttpMethodConstraints()
|
public void CreateControllerModel_DisableCorsGloballyEnablesCorsPreflight()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var corsProvider = new CorsApplicationModelProvider();
|
var corsProvider = new CorsApplicationModelProvider();
|
||||||
|
|
@ -169,10 +185,12 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.True(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateControllerModel_CustomCorsFilterGloballyReplacesHttpMethodConstraints()
|
public void CreateControllerModel_CustomCorsFilterGloballyEnablesCorsPreflight()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var corsProvider = new CorsApplicationModelProvider();
|
var corsProvider = new CorsApplicationModelProvider();
|
||||||
|
|
@ -188,6 +206,8 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.True(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -206,6 +226,8 @@ namespace Microsoft.AspNetCore.Mvc.Cors.Internal
|
||||||
var selector = Assert.Single(action.Selectors);
|
var selector = Assert.Single(action.Selectors);
|
||||||
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
var constraint = Assert.Single(selector.ActionConstraints, c => c is HttpMethodActionConstraint);
|
||||||
Assert.IsNotType<CorsHttpMethodActionConstraint>(constraint);
|
Assert.IsNotType<CorsHttpMethodActionConstraint>(constraint);
|
||||||
|
var httpMethodMetadata = Assert.Single(selector.EndpointMetadata.OfType<HttpMethodMetadata>());
|
||||||
|
Assert.False(httpMethodMetadata.AcceptCorsPreflight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ApplicationModelProviderContext GetProviderContext(Type controllerType)
|
private static ApplicationModelProviderContext GetProviderContext(Type controllerType)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
// 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.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
|
{
|
||||||
|
public class CorsGlobalRoutingTests : CorsTestsBase<CorsWebSite.StartupWithGlobalRouting>
|
||||||
|
{
|
||||||
|
public CorsGlobalRoutingTests(MvcTestFixture<CorsWebSite.StartupWithGlobalRouting> fixture)
|
||||||
|
: base(fixture)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // This intentionally returns a 405 with global routing
|
||||||
|
public override async Task PreflightRequestOnNonCorsEnabledController_DoesNotMatchTheAction()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(new HttpMethod("OPTIONS"), "http://localhost/NonCors/Post");
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "POST");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,354 +1,13 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
{
|
{
|
||||||
public class CorsTests : IClassFixture<MvcTestFixture<CorsWebSite.Startup>>
|
public class CorsTests : CorsTestsBase<CorsWebSite.Startup>
|
||||||
{
|
{
|
||||||
public CorsTests(MvcTestFixture<CorsWebSite.Startup> fixture)
|
public CorsTests(MvcTestFixture<CorsWebSite.Startup> fixture)
|
||||||
|
: base(fixture)
|
||||||
{
|
{
|
||||||
Client = fixture.CreateDefaultClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient Client { get; }
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("GET")]
|
|
||||||
[InlineData("HEAD")]
|
|
||||||
[InlineData("POST")]
|
|
||||||
public async Task ResourceWithSimpleRequestPolicy_Allows_SimpleRequests(string method)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var origin = "http://example.com";
|
|
||||||
var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Cors/GetBlogComments");
|
|
||||||
request.Headers.Add(CorsConstants.Origin, origin);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Equal("[\"comment1\",\"comment2\",\"comment3\"]", content);
|
|
||||||
var responseHeaders = response.Headers;
|
|
||||||
var header = Assert.Single(response.Headers);
|
|
||||||
Assert.Equal(CorsConstants.AccessControlAllowOrigin, header.Key);
|
|
||||||
Assert.Equal(new[] { "*" }, header.Value.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task OptionsRequest_NonPreflight_ExecutesOptionsAction()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(new HttpMethod("OPTIONS"), "http://localhost/NonCors/GetOptions");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Equal("[\"Create\",\"Update\",\"Delete\"]", content);
|
|
||||||
Assert.Empty(response.Headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task PreflightRequestOnNonCorsEnabledController_ExecutesOptionsAction()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(new HttpMethod("OPTIONS"), "http://localhost/NonCors/GetOptions");
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "POST");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Equal("[\"Create\",\"Update\",\"Delete\"]", content);
|
|
||||||
Assert.Empty(response.Headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task PreflightRequestOnNonCorsEnabledController_DoesNotMatchTheAction()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(new HttpMethod("OPTIONS"), "http://localhost/NonCors/Post");
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "POST");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("GET")]
|
|
||||||
[InlineData("HEAD")]
|
|
||||||
[InlineData("POST")]
|
|
||||||
[InlineData("PUT")]
|
|
||||||
public async Task PolicyFailed_Disallows_PreFlightRequest(string method)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(
|
|
||||||
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
|
||||||
"http://localhost/Cors/GetBlogComments");
|
|
||||||
|
|
||||||
// Adding a custom header makes it a non-simple request.
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestMethod, method);
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
// MVC applied the policy and since that did not pass, there were no access control headers.
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.Empty(response.Headers);
|
|
||||||
|
|
||||||
// It should short circuit and hence no result.
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Equal(string.Empty, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SuccessfulCorsRequest_AllowsCredentials_IfThePolicyAllowsCredentials()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(
|
|
||||||
HttpMethod.Put,
|
|
||||||
"http://localhost/Cors/EditUserComment?userComment=abcd");
|
|
||||||
|
|
||||||
// Adding a custom header makes it a non-simple request.
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlExposeHeaders, "exposed1,exposed2");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
var responseHeaders = response.Headers;
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "http://example.com" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlAllowOrigin).ToArray());
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "true" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlAllowCredentials).ToArray());
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "exposed1,exposed2" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlExposeHeaders).ToArray());
|
|
||||||
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Equal("abcd", content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task SuccessfulPreflightRequest_AllowsCredentials_IfThePolicyAllowsCredentials()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(
|
|
||||||
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
|
||||||
"http://localhost/Cors/EditUserComment?userComment=abcd");
|
|
||||||
|
|
||||||
// Adding a custom header makes it a non-simple request.
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "PUT");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "header1,header2");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
var responseHeaders = response.Headers;
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "http://example.com" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlAllowOrigin).ToArray());
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "true" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlAllowCredentials).ToArray());
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "header1,header2" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlAllowHeaders).ToArray());
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "PUT" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlAllowMethods).ToArray());
|
|
||||||
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Empty(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task PolicyFailed_Allows_ActualRequest_WithMissingResponseHeaders()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(HttpMethod.Put, "http://localhost/Cors/GetUserComments");
|
|
||||||
|
|
||||||
// Adding a custom header makes it a non simple request.
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example2.com");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
// MVC applied the policy and since that did not pass, there were no access control headers.
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.Empty(response.Headers);
|
|
||||||
|
|
||||||
// It still have executed the action.
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Equal("[\"usercomment1\",\"usercomment2\",\"usercomment3\"]", content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("GET")]
|
|
||||||
[InlineData("HEAD")]
|
|
||||||
[InlineData("POST")]
|
|
||||||
public async Task DisableCors_ActionsCanOverride_ControllerLevel(string method)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Cors/GetExclusiveContent");
|
|
||||||
|
|
||||||
// Exclusive content is not available on other sites.
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
|
|
||||||
// Since there are no response headers, the client should step in to block the content.
|
|
||||||
Assert.Empty(response.Headers);
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Equal("exclusive", content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("GET")]
|
|
||||||
[InlineData("HEAD")]
|
|
||||||
[InlineData("POST")]
|
|
||||||
public async Task DisableCors_PreFlight_ActionsCanOverride_ControllerLevel(string method)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(
|
|
||||||
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
|
||||||
"http://localhost/Cors/GetExclusiveContent");
|
|
||||||
|
|
||||||
// Exclusive content is not available on other sites.
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestMethod, method);
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
// Since there are no response headers, the client should step in to block the content.
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.Empty(response.Headers);
|
|
||||||
|
|
||||||
// Nothing gets executed for a pre-flight request.
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Empty(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("http://localhost/api/store/actionusingcontrollercorssettings")]
|
|
||||||
[InlineData("http://localhost/api/store/actionwithcorssettings")]
|
|
||||||
public async Task CorsFilter_RunsBeforeOtherAuthorizationFilters(string url)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(new HttpMethod(CorsConstants.PreflightHttpMethod), url);
|
|
||||||
|
|
||||||
// Adding a custom header makes it a non-simple request.
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "GET");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
var responseHeaders = response.Headers;
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "http://example.com" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlAllowOrigin).ToArray());
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "true" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlAllowCredentials).ToArray());
|
|
||||||
Assert.Equal(
|
|
||||||
new[] { "Custom" },
|
|
||||||
responseHeaders.GetValues(CorsConstants.AccessControlAllowHeaders).ToArray());
|
|
||||||
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Empty(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task DisableCorsFilter_RunsBeforeOtherAuthorizationFilters()
|
|
||||||
{
|
|
||||||
// Controller has an authorization filter and Cors filter and the action has a DisableCors filter
|
|
||||||
// In this scenario, the CorsFilter should be executed before any other authorization filters
|
|
||||||
// i.e irrespective of where the Cors filter is applied(controller or action), Cors filters must
|
|
||||||
// always be executed before any other type of authorization filters.
|
|
||||||
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(
|
|
||||||
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
|
||||||
"http://localhost/api/store/actionwithcorsdisabled");
|
|
||||||
|
|
||||||
// Adding a custom header makes it a non-simple request.
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "GET");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.Empty(response.Headers);
|
|
||||||
|
|
||||||
// Nothing gets executed for a pre-flight request.
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Empty(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task CorsFilter_OnAction_PreferredOverController_AndAuthorizationFiltersRunAfterCors()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var request = new HttpRequestMessage(
|
|
||||||
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
|
||||||
"http://localhost/api/store/actionwithdifferentcorspolicy");
|
|
||||||
request.Headers.Add(CorsConstants.Origin, "http://notexpecteddomain.com");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "GET");
|
|
||||||
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var response = await Client.SendAsync(request);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.Empty(response.Headers);
|
|
||||||
|
|
||||||
// Nothing gets executed for a pre-flight request.
|
|
||||||
var content = await response.Content.ReadAsStringAsync();
|
|
||||||
Assert.Empty(content);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,359 @@
|
||||||
|
// 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.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
|
{
|
||||||
|
public abstract class CorsTestsBase<TStartup> : IClassFixture<MvcTestFixture<TStartup>> where TStartup : class
|
||||||
|
{
|
||||||
|
protected CorsTestsBase(MvcTestFixture<TStartup> fixture)
|
||||||
|
{
|
||||||
|
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||||
|
Client = factory.CreateDefaultClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||||
|
builder.UseStartup<TStartup>();
|
||||||
|
|
||||||
|
public HttpClient Client { get; }
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("GET")]
|
||||||
|
[InlineData("HEAD")]
|
||||||
|
[InlineData("POST")]
|
||||||
|
public async Task ResourceWithSimpleRequestPolicy_Allows_SimpleRequests(string method)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var origin = "http://example.com";
|
||||||
|
var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Cors/GetBlogComments");
|
||||||
|
request.Headers.Add(CorsConstants.Origin, origin);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal("[\"comment1\",\"comment2\",\"comment3\"]", content);
|
||||||
|
var responseHeaders = response.Headers;
|
||||||
|
var header = Assert.Single(response.Headers);
|
||||||
|
Assert.Equal(CorsConstants.AccessControlAllowOrigin, header.Key);
|
||||||
|
Assert.Equal(new[] { "*" }, header.Value.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task OptionsRequest_NonPreflight_ExecutesOptionsAction()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(new HttpMethod("OPTIONS"), "http://localhost/NonCors/GetOptions");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal("[\"Create\",\"Update\",\"Delete\"]", content);
|
||||||
|
Assert.Empty(response.Headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PreflightRequestOnNonCorsEnabledController_ExecutesOptionsAction()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(new HttpMethod("OPTIONS"), "http://localhost/NonCors/GetOptions");
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "POST");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal("[\"Create\",\"Update\",\"Delete\"]", content);
|
||||||
|
Assert.Empty(response.Headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public virtual async Task PreflightRequestOnNonCorsEnabledController_DoesNotMatchTheAction()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(new HttpMethod("OPTIONS"), "http://localhost/NonCors/Post");
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "POST");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("GET")]
|
||||||
|
[InlineData("HEAD")]
|
||||||
|
[InlineData("POST")]
|
||||||
|
[InlineData("PUT")]
|
||||||
|
public async Task PolicyFailed_Disallows_PreFlightRequest(string method)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(
|
||||||
|
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
||||||
|
"http://localhost/Cors/GetBlogComments");
|
||||||
|
|
||||||
|
// Adding a custom header makes it a non-simple request.
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestMethod, method);
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// MVC applied the policy and since that did not pass, there were no access control headers.
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Empty(response.Headers);
|
||||||
|
|
||||||
|
// It should short circuit and hence no result.
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal(string.Empty, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SuccessfulCorsRequest_AllowsCredentials_IfThePolicyAllowsCredentials()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(
|
||||||
|
HttpMethod.Put,
|
||||||
|
"http://localhost/Cors/EditUserComment?userComment=abcd");
|
||||||
|
|
||||||
|
// Adding a custom header makes it a non-simple request.
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlExposeHeaders, "exposed1,exposed2");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
var responseHeaders = response.Headers;
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "http://example.com" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlAllowOrigin).ToArray());
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "true" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlAllowCredentials).ToArray());
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "exposed1,exposed2" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlExposeHeaders).ToArray());
|
||||||
|
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal("abcd", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SuccessfulPreflightRequest_AllowsCredentials_IfThePolicyAllowsCredentials()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(
|
||||||
|
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
||||||
|
"http://localhost/Cors/EditUserComment?userComment=abcd");
|
||||||
|
|
||||||
|
// Adding a custom header makes it a non-simple request.
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "PUT");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "header1,header2");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
var responseHeaders = response.Headers;
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "http://example.com" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlAllowOrigin).ToArray());
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "true" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlAllowCredentials).ToArray());
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "header1,header2" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlAllowHeaders).ToArray());
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "PUT" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlAllowMethods).ToArray());
|
||||||
|
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Empty(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PolicyFailed_Allows_ActualRequest_WithMissingResponseHeaders()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Put, "http://localhost/Cors/GetUserComments");
|
||||||
|
|
||||||
|
// Adding a custom header makes it a non simple request.
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example2.com");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// MVC applied the policy and since that did not pass, there were no access control headers.
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Empty(response.Headers);
|
||||||
|
|
||||||
|
// It still have executed the action.
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal("[\"usercomment1\",\"usercomment2\",\"usercomment3\"]", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("GET")]
|
||||||
|
[InlineData("HEAD")]
|
||||||
|
[InlineData("POST")]
|
||||||
|
public async Task DisableCors_ActionsCanOverride_ControllerLevel(string method)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Cors/GetExclusiveContent");
|
||||||
|
|
||||||
|
// Exclusive content is not available on other sites.
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
|
||||||
|
// Since there are no response headers, the client should step in to block the content.
|
||||||
|
Assert.Empty(response.Headers);
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal("exclusive", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("GET")]
|
||||||
|
[InlineData("HEAD")]
|
||||||
|
[InlineData("POST")]
|
||||||
|
public async Task DisableCors_PreFlight_ActionsCanOverride_ControllerLevel(string method)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(
|
||||||
|
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
||||||
|
"http://localhost/Cors/GetExclusiveContent");
|
||||||
|
|
||||||
|
// Exclusive content is not available on other sites.
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestMethod, method);
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// Since there are no response headers, the client should step in to block the content.
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Empty(response.Headers);
|
||||||
|
|
||||||
|
// Nothing gets executed for a pre-flight request.
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Empty(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("http://localhost/api/store/actionusingcontrollercorssettings")]
|
||||||
|
[InlineData("http://localhost/api/store/actionwithcorssettings")]
|
||||||
|
public async Task CorsFilter_RunsBeforeOtherAuthorizationFilters(string url)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(new HttpMethod(CorsConstants.PreflightHttpMethod), url);
|
||||||
|
|
||||||
|
// Adding a custom header makes it a non-simple request.
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "GET");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
var responseHeaders = response.Headers;
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "http://example.com" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlAllowOrigin).ToArray());
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "true" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlAllowCredentials).ToArray());
|
||||||
|
Assert.Equal(
|
||||||
|
new[] { "Custom" },
|
||||||
|
responseHeaders.GetValues(CorsConstants.AccessControlAllowHeaders).ToArray());
|
||||||
|
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Empty(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task DisableCorsFilter_RunsBeforeOtherAuthorizationFilters()
|
||||||
|
{
|
||||||
|
// Controller has an authorization filter and Cors filter and the action has a DisableCors filter
|
||||||
|
// In this scenario, the CorsFilter should be executed before any other authorization filters
|
||||||
|
// i.e irrespective of where the Cors filter is applied(controller or action), Cors filters must
|
||||||
|
// always be executed before any other type of authorization filters.
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(
|
||||||
|
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
||||||
|
"http://localhost/api/store/actionwithcorsdisabled");
|
||||||
|
|
||||||
|
// Adding a custom header makes it a non-simple request.
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://example.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "GET");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Empty(response.Headers);
|
||||||
|
|
||||||
|
// Nothing gets executed for a pre-flight request.
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Empty(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CorsFilter_OnAction_PreferredOverController_AndAuthorizationFiltersRunAfterCors()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var request = new HttpRequestMessage(
|
||||||
|
new HttpMethod(CorsConstants.PreflightHttpMethod),
|
||||||
|
"http://localhost/api/store/actionwithdifferentcorspolicy");
|
||||||
|
request.Headers.Add(CorsConstants.Origin, "http://notexpecteddomain.com");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestMethod, "GET");
|
||||||
|
request.Headers.Add(CorsConstants.AccessControlRequestHeaders, "Custom");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Empty(response.Headers);
|
||||||
|
|
||||||
|
// Nothing gets executed for a pre-flight request.
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Empty(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -29,5 +30,27 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
|
|
||||||
Assert.True(result);
|
Assert.True(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This behaves differently right now because the action/endpoint constraints are always
|
||||||
|
// executed after the DFA nodes like (HttpMethodMatcherPolicy). You don't have the flexibility
|
||||||
|
// to do what this test is doing in old-style routing.
|
||||||
|
[Fact]
|
||||||
|
public override async Task VersionedApi_CanUseConstraintOrder_ToChangeSelectedAction()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var message = new HttpRequestMessage(HttpMethod.Delete, "http://localhost/" + "Customers/5?version=2");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(message);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
|
||||||
|
var body = await response.Content.ReadAsStringAsync();
|
||||||
|
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||||
|
|
||||||
|
Assert.Equal("Customers", result.Controller);
|
||||||
|
Assert.Equal("AnyV2OrHigherWithId", result.Action);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -508,7 +508,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task VersionedApi_CanUseConstraintOrder_ToChangeSelectedAction()
|
public virtual async Task VersionedApi_CanUseConstraintOrder_ToChangeSelectedAction()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var message = new HttpRequestMessage(HttpMethod.Delete, "http://localhost/" + "Customers/5?version=2");
|
var message = new HttpRequestMessage(HttpMethod.Delete, "http://localhost/" + "Customers/5?version=2");
|
||||||
|
|
@ -551,7 +551,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
Assert.Equal(path, actualUrl);
|
Assert.Equal(path, actualUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RoutingResult
|
protected class RoutingResult
|
||||||
{
|
{
|
||||||
public string[] ExpectedUrls { get; set; }
|
public string[] ExpectedUrls { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// 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.IO;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
|
||||||
|
namespace CorsWebSite
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var host = CreateWebHostBuilder(args)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
host.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||||
|
new WebHostBuilder()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseStartup<Startup>()
|
||||||
|
.UseKestrel()
|
||||||
|
.UseIISIntegration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -76,20 +76,5 @@ namespace CorsWebSite
|
||||||
{
|
{
|
||||||
app.UseMvc();
|
app.UseMvc();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
var host = CreateWebHostBuilder(args)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
host.Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
|
||||||
new WebHostBuilder()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseStartup<Startup>()
|
|
||||||
.UseKestrel()
|
|
||||||
.UseIISIntegration();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
// 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.IO;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace CorsWebSite
|
||||||
|
{
|
||||||
|
public class StartupWithGlobalRouting
|
||||||
|
{
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddMvc(options => options.EnableGlobalRouting = true);
|
||||||
|
services.Configure<CorsOptions>(options =>
|
||||||
|
{
|
||||||
|
options.AddPolicy(
|
||||||
|
"AllowAnySimpleRequest",
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.AllowAnyOrigin()
|
||||||
|
.WithMethods("GET", "POST", "HEAD");
|
||||||
|
});
|
||||||
|
|
||||||
|
options.AddPolicy(
|
||||||
|
"AllowSpecificOrigin",
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.WithOrigins("http://example.com");
|
||||||
|
});
|
||||||
|
|
||||||
|
options.AddPolicy(
|
||||||
|
"WithCredentials",
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.AllowCredentials()
|
||||||
|
.WithOrigins("http://example.com");
|
||||||
|
});
|
||||||
|
|
||||||
|
options.AddPolicy(
|
||||||
|
"WithCredentialsAnyOrigin",
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.AllowCredentials()
|
||||||
|
.AllowAnyOrigin()
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.WithMethods("PUT", "POST")
|
||||||
|
.WithExposedHeaders("exposed1", "exposed2");
|
||||||
|
});
|
||||||
|
|
||||||
|
options.AddPolicy(
|
||||||
|
"AllowAll",
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.AllowCredentials()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowAnyOrigin();
|
||||||
|
});
|
||||||
|
|
||||||
|
options.AddPolicy(
|
||||||
|
"Allow example.com",
|
||||||
|
builder =>
|
||||||
|
{
|
||||||
|
builder.AllowCredentials()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.WithOrigins("http://example.com");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseMvc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue