Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/aspnetcore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>2022-06-29 00:53:32 +0300
committerGitHub <noreply@github.com>2022-06-29 00:53:32 +0300
commit19a2bd0b050d543665b26c7e14872f6999315c43 (patch)
treea3ffbfde9e855a90b9ca6a2e322f0e21538b0db9
parent32dfb4184730ac0015531a4f87dc6208057d55b3 (diff)
[release/7.0-preview6] Update dependencies from dotnet/runtime dotnet/efcore (#42358)
* Update dependencies from https://github.com/dotnet/efcore build 20220622.4 dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Design , Microsoft.EntityFrameworkCore.InMemory , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.SqlServer , Microsoft.EntityFrameworkCore.Tools From Version 7.0.0-preview.6.22322.3 -> To Version 7.0.0-preview.6.22322.4 * Update dependencies from https://github.com/dotnet/runtime build 20220623.3 Microsoft.Extensions.Caching.Abstractions , Microsoft.Extensions.Caching.Memory , Microsoft.Extensions.Configuration , Microsoft.Extensions.Configuration.Abstractions , Microsoft.Extensions.Configuration.Binder , Microsoft.Extensions.Configuration.CommandLine , Microsoft.Extensions.Configuration.EnvironmentVariables , Microsoft.Extensions.Configuration.FileExtensions , Microsoft.Extensions.Configuration.Ini , Microsoft.Extensions.Configuration.Json , Microsoft.Extensions.Configuration.UserSecrets , Microsoft.Extensions.Configuration.Xml , Microsoft.Extensions.DependencyInjection , Microsoft.Extensions.DependencyInjection.Abstractions , Microsoft.Extensions.DependencyModel , Microsoft.Extensions.FileProviders.Abstractions , Microsoft.Extensions.FileProviders.Composite , Microsoft.Extensions.FileProviders.Physical , Microsoft.Extensions.FileSystemGlobbing , Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.Extensions.Hosting , Microsoft.Extensions.Hosting.Abstractions , Microsoft.Extensions.Http , Microsoft.Extensions.Logging , Microsoft.Extensions.Logging.Abstractions , Microsoft.Extensions.Logging.Configuration , Microsoft.Extensions.Logging.Console , Microsoft.Extensions.Logging.Debug , Microsoft.Extensions.Logging.EventLog , Microsoft.Extensions.Logging.EventSource , Microsoft.Extensions.Logging.TraceSource , Microsoft.Extensions.Options , Microsoft.Extensions.Options.ConfigurationExtensions , Microsoft.Extensions.Options.DataAnnotations , Microsoft.Extensions.Primitives , Microsoft.Internal.Runtime.AspNetCore.Transport , Microsoft.NET.Runtime.MonoAOTCompiler.Task , Microsoft.NET.Runtime.WebAssembly.Sdk , Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NETCore.BrowserDebugHost.Transport , Microsoft.NETCore.Platforms , System.Configuration.ConfigurationManager , System.Diagnostics.DiagnosticSource , System.Diagnostics.EventLog , System.DirectoryServices.Protocols , System.IO.Pipelines , System.Net.Http.Json , System.Net.Http.WinHttpHandler , System.Reflection.Metadata , System.Resources.Extensions , System.Security.Cryptography.Pkcs , System.Security.Cryptography.Xml , System.Security.Permissions , System.ServiceProcess.ServiceController , System.Text.Encodings.Web , System.Text.Json , System.Threading.AccessControl , System.Threading.Channels , System.Threading.RateLimiting From Version 7.0.0-preview.6.22321.8 -> To Version 7.0.0-preview.6.22323.3 * Update dependencies from https://github.com/dotnet/runtime build 20220623.6 Microsoft.Extensions.Caching.Abstractions , Microsoft.Extensions.Caching.Memory , Microsoft.Extensions.Configuration , Microsoft.Extensions.Configuration.Abstractions , Microsoft.Extensions.Configuration.Binder , Microsoft.Extensions.Configuration.CommandLine , Microsoft.Extensions.Configuration.EnvironmentVariables , Microsoft.Extensions.Configuration.FileExtensions , Microsoft.Extensions.Configuration.Ini , Microsoft.Extensions.Configuration.Json , Microsoft.Extensions.Configuration.UserSecrets , Microsoft.Extensions.Configuration.Xml , Microsoft.Extensions.DependencyInjection , Microsoft.Extensions.DependencyInjection.Abstractions , Microsoft.Extensions.DependencyModel , Microsoft.Extensions.FileProviders.Abstractions , Microsoft.Extensions.FileProviders.Composite , Microsoft.Extensions.FileProviders.Physical , Microsoft.Extensions.FileSystemGlobbing , Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.Extensions.Hosting , Microsoft.Extensions.Hosting.Abstractions , Microsoft.Extensions.Http , Microsoft.Extensions.Logging , Microsoft.Extensions.Logging.Abstractions , Microsoft.Extensions.Logging.Configuration , Microsoft.Extensions.Logging.Console , Microsoft.Extensions.Logging.Debug , Microsoft.Extensions.Logging.EventLog , Microsoft.Extensions.Logging.EventSource , Microsoft.Extensions.Logging.TraceSource , Microsoft.Extensions.Options , Microsoft.Extensions.Options.ConfigurationExtensions , Microsoft.Extensions.Options.DataAnnotations , Microsoft.Extensions.Primitives , Microsoft.Internal.Runtime.AspNetCore.Transport , Microsoft.NET.Runtime.MonoAOTCompiler.Task , Microsoft.NET.Runtime.WebAssembly.Sdk , Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NETCore.BrowserDebugHost.Transport , Microsoft.NETCore.Platforms , System.Configuration.ConfigurationManager , System.Diagnostics.DiagnosticSource , System.Diagnostics.EventLog , System.DirectoryServices.Protocols , System.IO.Pipelines , System.Net.Http.Json , System.Net.Http.WinHttpHandler , System.Reflection.Metadata , System.Resources.Extensions , System.Security.Cryptography.Pkcs , System.Security.Cryptography.Xml , System.Security.Permissions , System.ServiceProcess.ServiceController , System.Text.Encodings.Web , System.Text.Json , System.Threading.AccessControl , System.Threading.Channels , System.Threading.RateLimiting From Version 7.0.0-preview.6.22321.8 -> To Version 7.0.0-preview.6.22323.6 * Update dependencies from https://github.com/dotnet/efcore build 20220623.4 dotnet-ef , Microsoft.EntityFrameworkCore , Microsoft.EntityFrameworkCore.Design , Microsoft.EntityFrameworkCore.InMemory , Microsoft.EntityFrameworkCore.Relational , Microsoft.EntityFrameworkCore.Sqlite , Microsoft.EntityFrameworkCore.SqlServer , Microsoft.EntityFrameworkCore.Tools From Version 7.0.0-preview.6.22322.3 -> To Version 7.0.0-preview.6.22323.4 Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
-rw-r--r--eng/Version.Details.xml276
-rw-r--r--eng/Versions.props144
-rw-r--r--src/Middleware/OutputCaching/test/MemoryOutputCacheStoreTests.cs14
-rw-r--r--src/Middleware/OutputCaching/test/OutputCacheEntryFormatterTests.cs2
-rw-r--r--src/Middleware/RateLimiting/src/DefaultCombinedLease.cs98
-rw-r--r--src/Middleware/RateLimiting/src/DefaultKeyType.T.cs19
-rw-r--r--src/Middleware/RateLimiting/src/DefaultKeyType.cs9
-rw-r--r--src/Middleware/RateLimiting/src/DefaultKeyTypeEqualityComparer.cs44
-rw-r--r--src/Middleware/RateLimiting/src/DefaultRateLimiterPolicy.cs25
-rw-r--r--src/Middleware/RateLimiting/src/IRateLimiterMetadata.cs15
-rw-r--r--src/Middleware/RateLimiting/src/IRateLimiterPolicy.cs24
-rw-r--r--src/Middleware/RateLimiting/src/LeaseContext.cs17
-rw-r--r--src/Middleware/RateLimiting/src/NoLimiter.cs36
-rw-r--r--src/Middleware/RateLimiting/src/OnRejectedContext.cs23
-rw-r--r--src/Middleware/RateLimiting/src/PolicyNameKey.cs22
-rw-r--r--src/Middleware/RateLimiting/src/PolicyTypeInfo.cs12
-rw-r--r--src/Middleware/RateLimiting/src/PublicAPI.Unshipped.txt36
-rw-r--r--src/Middleware/RateLimiting/src/RateLimiterApplicationBuilderExtensions.cs (renamed from src/Middleware/RateLimiting/src/RateLimitingApplicationBuilderExtensions.cs)6
-rw-r--r--src/Middleware/RateLimiting/src/RateLimiterEndpointConventionBuilderExtensions.cs38
-rw-r--r--src/Middleware/RateLimiting/src/RateLimiterMetadata.cs24
-rw-r--r--src/Middleware/RateLimiting/src/RateLimiterOptions.cs135
-rw-r--r--src/Middleware/RateLimiting/src/RateLimiterOptionsExtensions.cs90
-rw-r--r--src/Middleware/RateLimiting/src/RateLimitingMiddleware.cs142
-rw-r--r--src/Middleware/RateLimiting/test/RateLimitingApplicationBuilderExtensionsTests.cs10
-rw-r--r--src/Middleware/RateLimiting/test/RateLimitingMiddlewareTests.cs329
-rw-r--r--src/Middleware/RateLimiting/test/RateLimitingOptionsTests.cs33
-rw-r--r--src/Middleware/RateLimiting/test/TestRateLimiterPolicy.cs35
27 files changed, 1318 insertions, 340 deletions
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 6c3a14c54f..5f08da848d 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -9,288 +9,288 @@
-->
<Dependencies>
<ProductDependencies>
- <Dependency Name="dotnet-ef" Version="7.0.0-preview.6.22322.3">
+ <Dependency Name="dotnet-ef" Version="7.0.0-preview.6.22323.4">
<Uri>https://github.com/dotnet/efcore</Uri>
- <Sha>5618bc6a0aa2e0dfed57c0f3cd64830733e7c924</Sha>
+ <Sha>380454af37a6c779763f2bd95360c0797ce980b6</Sha>
</Dependency>
- <Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0-preview.6.22322.3">
+ <Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0-preview.6.22323.4">
<Uri>https://github.com/dotnet/efcore</Uri>
- <Sha>5618bc6a0aa2e0dfed57c0f3cd64830733e7c924</Sha>
+ <Sha>380454af37a6c779763f2bd95360c0797ce980b6</Sha>
</Dependency>
- <Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="7.0.0-preview.6.22322.3">
+ <Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="7.0.0-preview.6.22323.4">
<Uri>https://github.com/dotnet/efcore</Uri>
- <Sha>5618bc6a0aa2e0dfed57c0f3cd64830733e7c924</Sha>
+ <Sha>380454af37a6c779763f2bd95360c0797ce980b6</Sha>
</Dependency>
- <Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0-preview.6.22322.3">
+ <Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0-preview.6.22323.4">
<Uri>https://github.com/dotnet/efcore</Uri>
- <Sha>5618bc6a0aa2e0dfed57c0f3cd64830733e7c924</Sha>
+ <Sha>380454af37a6c779763f2bd95360c0797ce980b6</Sha>
</Dependency>
- <Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0-preview.6.22322.3">
+ <Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0-preview.6.22323.4">
<Uri>https://github.com/dotnet/efcore</Uri>
- <Sha>5618bc6a0aa2e0dfed57c0f3cd64830733e7c924</Sha>
+ <Sha>380454af37a6c779763f2bd95360c0797ce980b6</Sha>
</Dependency>
- <Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0-preview.6.22322.3">
+ <Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0-preview.6.22323.4">
<Uri>https://github.com/dotnet/efcore</Uri>
- <Sha>5618bc6a0aa2e0dfed57c0f3cd64830733e7c924</Sha>
+ <Sha>380454af37a6c779763f2bd95360c0797ce980b6</Sha>
</Dependency>
- <Dependency Name="Microsoft.EntityFrameworkCore" Version="7.0.0-preview.6.22322.3">
+ <Dependency Name="Microsoft.EntityFrameworkCore" Version="7.0.0-preview.6.22323.4">
<Uri>https://github.com/dotnet/efcore</Uri>
- <Sha>5618bc6a0aa2e0dfed57c0f3cd64830733e7c924</Sha>
+ <Sha>380454af37a6c779763f2bd95360c0797ce980b6</Sha>
</Dependency>
- <Dependency Name="Microsoft.EntityFrameworkCore.Design" Version="7.0.0-preview.6.22322.3">
+ <Dependency Name="Microsoft.EntityFrameworkCore.Design" Version="7.0.0-preview.6.22323.4">
<Uri>https://github.com/dotnet/efcore</Uri>
- <Sha>5618bc6a0aa2e0dfed57c0f3cd64830733e7c924</Sha>
+ <Sha>380454af37a6c779763f2bd95360c0797ce980b6</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Caching.Memory" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Caching.Memory" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration.Json" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration.Json" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Configuration" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Configuration" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.DependencyInjection" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.DependencyInjection" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Hosting" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Hosting" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Http" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Http" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Logging.Console" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Logging.Console" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Logging.Debug" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Logging.Debug" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Logging" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Logging" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Options" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Options" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.Primitives" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.Primitives" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Internal.Runtime.AspNetCore.Transport" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Internal.Runtime.AspNetCore.Transport" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Configuration.ConfigurationManager" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Configuration.ConfigurationManager" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Diagnostics.DiagnosticSource" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Diagnostics.DiagnosticSource" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Diagnostics.EventLog" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Diagnostics.EventLog" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.DirectoryServices.Protocols" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.DirectoryServices.Protocols" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.IO.Pipelines" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.IO.Pipelines" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Net.Http.Json" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Net.Http.Json" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Net.Http.WinHttpHandler" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Net.Http.WinHttpHandler" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Reflection.Metadata" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Reflection.Metadata" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Resources.Extensions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Resources.Extensions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Security.Cryptography.Pkcs" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Security.Cryptography.Pkcs" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Security.Cryptography.Xml" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Security.Cryptography.Xml" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Security.Permissions" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Security.Permissions" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.ServiceProcess.ServiceController" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.ServiceProcess.ServiceController" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Text.Encodings.Web" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Text.Encodings.Web" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Text.Json" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Text.Json" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Threading.AccessControl" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Threading.AccessControl" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Threading.Channels" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Threading.Channels" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="System.Threading.RateLimiting" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="System.Threading.RateLimiting" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.Extensions.DependencyModel" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.Extensions.DependencyModel" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.NETCore.App.Ref" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.NETCore.App.Ref" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.NET.Runtime.MonoAOTCompiler.Task" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.NET.Runtime.MonoAOTCompiler.Task" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.NET.Runtime.WebAssembly.Sdk" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.NET.Runtime.WebAssembly.Sdk" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
<!--
Win-x64 is used here because we have picked an arbitrary runtime identifier to flow the version of the latest NETCore.App runtime.
All Runtime.$rid packages should have the same version.
-->
- <Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
- <Dependency Name="Microsoft.NETCore.BrowserDebugHost.Transport" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.NETCore.BrowserDebugHost.Transport" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
<!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
- <Dependency Name="Microsoft.NETCore.Platforms" Version="7.0.0-preview.6.22321.8">
+ <Dependency Name="Microsoft.NETCore.Platforms" Version="7.0.0-preview.6.22323.6">
<Uri>https://github.com/dotnet/runtime</Uri>
- <Sha>fdc3b51da075066a5da489be2c169be85dbc117f</Sha>
+ <Sha>e45c708c41a9fdec2545b2ae517739a122f7b66b</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="7.0.0-beta.22316.2">
<Uri>https://github.com/dotnet/arcade</Uri>
diff --git a/eng/Versions.props b/eng/Versions.props
index 995788c456..b70a0ee979 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -50,6 +50,8 @@
<UsingToolNetFrameworkReferenceAssemblies Condition="'$(OS)' != 'Windows_NT'">true</UsingToolNetFrameworkReferenceAssemblies>
<!-- Disable XLIFF tasks -->
<UsingToolXliff>false</UsingToolXliff>
+ <!-- Use custom version of Roslyn Compiler -->
+ <UsingToolMicrosoftNetCompilers>true</UsingToolMicrosoftNetCompilers>
</PropertyGroup>
<!--
@@ -63,77 +65,77 @@
-->
<PropertyGroup Label="Automated">
<!-- Packages from dotnet/runtime -->
- <MicrosoftExtensionsDependencyModelVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsDependencyModelVersion>
- <MicrosoftNETCoreAppRefVersion>7.0.0-preview.6.22321.8</MicrosoftNETCoreAppRefVersion>
- <MicrosoftNETCoreAppRuntimewinx64Version>7.0.0-preview.6.22321.8</MicrosoftNETCoreAppRuntimewinx64Version>
- <MicrosoftNETRuntimeMonoAOTCompilerTaskVersion>7.0.0-preview.6.22321.8</MicrosoftNETRuntimeMonoAOTCompilerTaskVersion>
- <MicrosoftNETRuntimeWebAssemblySdkVersion>7.0.0-preview.6.22321.8</MicrosoftNETRuntimeWebAssemblySdkVersion>
- <MicrosoftNETCoreAppRuntimeAOTwinx64CrossbrowserwasmVersion>7.0.0-preview.6.22321.8</MicrosoftNETCoreAppRuntimeAOTwinx64CrossbrowserwasmVersion>
- <MicrosoftNETCoreBrowserDebugHostTransportVersion>7.0.0-preview.6.22321.8</MicrosoftNETCoreBrowserDebugHostTransportVersion>
- <MicrosoftExtensionsCachingAbstractionsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsCachingAbstractionsVersion>
- <MicrosoftExtensionsCachingMemoryVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsCachingMemoryVersion>
- <MicrosoftExtensionsConfigurationAbstractionsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationAbstractionsVersion>
- <MicrosoftExtensionsConfigurationBinderVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationBinderVersion>
- <MicrosoftExtensionsConfigurationCommandLineVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationCommandLineVersion>
- <MicrosoftExtensionsConfigurationEnvironmentVariablesVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationEnvironmentVariablesVersion>
- <MicrosoftExtensionsConfigurationFileExtensionsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationFileExtensionsVersion>
- <MicrosoftExtensionsConfigurationIniVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationIniVersion>
- <MicrosoftExtensionsConfigurationJsonVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationJsonVersion>
- <MicrosoftExtensionsConfigurationVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationVersion>
- <MicrosoftExtensionsConfigurationUserSecretsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationUserSecretsVersion>
- <MicrosoftExtensionsConfigurationXmlVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsConfigurationXmlVersion>
- <MicrosoftExtensionsDependencyInjectionAbstractionsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsDependencyInjectionAbstractionsVersion>
- <MicrosoftExtensionsDependencyInjectionVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsDependencyInjectionVersion>
- <MicrosoftExtensionsFileProvidersAbstractionsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsFileProvidersAbstractionsVersion>
- <MicrosoftExtensionsFileProvidersCompositeVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsFileProvidersCompositeVersion>
- <MicrosoftExtensionsFileProvidersPhysicalVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsFileProvidersPhysicalVersion>
- <MicrosoftExtensionsFileSystemGlobbingVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsFileSystemGlobbingVersion>
- <MicrosoftExtensionsHostFactoryResolverSourcesVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsHostFactoryResolverSourcesVersion>
- <MicrosoftExtensionsHostingAbstractionsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsHostingAbstractionsVersion>
- <MicrosoftExtensionsHostingVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsHostingVersion>
- <MicrosoftExtensionsHttpVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsHttpVersion>
- <MicrosoftExtensionsLoggingAbstractionsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsLoggingAbstractionsVersion>
- <MicrosoftExtensionsLoggingConfigurationVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsLoggingConfigurationVersion>
- <MicrosoftExtensionsLoggingConsoleVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsLoggingConsoleVersion>
- <MicrosoftExtensionsLoggingDebugVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsLoggingDebugVersion>
- <MicrosoftExtensionsLoggingEventSourceVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsLoggingEventSourceVersion>
- <MicrosoftExtensionsLoggingEventLogVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsLoggingEventLogVersion>
- <MicrosoftExtensionsLoggingVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsLoggingVersion>
- <MicrosoftExtensionsLoggingTraceSourceVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsLoggingTraceSourceVersion>
- <MicrosoftExtensionsOptionsConfigurationExtensionsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsOptionsConfigurationExtensionsVersion>
- <MicrosoftExtensionsOptionsDataAnnotationsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsOptionsDataAnnotationsVersion>
- <MicrosoftExtensionsOptionsVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsOptionsVersion>
- <MicrosoftExtensionsPrimitivesVersion>7.0.0-preview.6.22321.8</MicrosoftExtensionsPrimitivesVersion>
- <MicrosoftInternalRuntimeAspNetCoreTransportVersion>7.0.0-preview.6.22321.8</MicrosoftInternalRuntimeAspNetCoreTransportVersion>
- <SystemConfigurationConfigurationManagerVersion>7.0.0-preview.6.22321.8</SystemConfigurationConfigurationManagerVersion>
- <SystemDiagnosticsDiagnosticSourceVersion>7.0.0-preview.6.22321.8</SystemDiagnosticsDiagnosticSourceVersion>
- <SystemDiagnosticsEventLogVersion>7.0.0-preview.6.22321.8</SystemDiagnosticsEventLogVersion>
- <SystemDirectoryServicesProtocolsVersion>7.0.0-preview.6.22321.8</SystemDirectoryServicesProtocolsVersion>
- <SystemIOPipelinesVersion>7.0.0-preview.6.22321.8</SystemIOPipelinesVersion>
- <SystemNetHttpJsonVersion>7.0.0-preview.6.22321.8</SystemNetHttpJsonVersion>
- <SystemNetHttpWinHttpHandlerVersion>7.0.0-preview.6.22321.8</SystemNetHttpWinHttpHandlerVersion>
- <SystemReflectionMetadataVersion>7.0.0-preview.6.22321.8</SystemReflectionMetadataVersion>
- <SystemResourcesExtensionsVersion>7.0.0-preview.6.22321.8</SystemResourcesExtensionsVersion>
- <SystemSecurityCryptographyPkcsVersion>7.0.0-preview.6.22321.8</SystemSecurityCryptographyPkcsVersion>
- <SystemSecurityCryptographyXmlVersion>7.0.0-preview.6.22321.8</SystemSecurityCryptographyXmlVersion>
- <SystemSecurityPermissionsVersion>7.0.0-preview.6.22321.8</SystemSecurityPermissionsVersion>
- <SystemServiceProcessServiceControllerVersion>7.0.0-preview.6.22321.8</SystemServiceProcessServiceControllerVersion>
- <SystemTextEncodingsWebVersion>7.0.0-preview.6.22321.8</SystemTextEncodingsWebVersion>
- <SystemTextJsonVersion>7.0.0-preview.6.22321.8</SystemTextJsonVersion>
- <SystemThreadingAccessControlVersion>7.0.0-preview.6.22321.8</SystemThreadingAccessControlVersion>
- <SystemThreadingChannelsVersion>7.0.0-preview.6.22321.8</SystemThreadingChannelsVersion>
- <SystemThreadingRateLimitingVersion>7.0.0-preview.6.22321.8</SystemThreadingRateLimitingVersion>
+ <MicrosoftExtensionsDependencyModelVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsDependencyModelVersion>
+ <MicrosoftNETCoreAppRefVersion>7.0.0-preview.6.22323.6</MicrosoftNETCoreAppRefVersion>
+ <MicrosoftNETCoreAppRuntimewinx64Version>7.0.0-preview.6.22323.6</MicrosoftNETCoreAppRuntimewinx64Version>
+ <MicrosoftNETRuntimeMonoAOTCompilerTaskVersion>7.0.0-preview.6.22323.6</MicrosoftNETRuntimeMonoAOTCompilerTaskVersion>
+ <MicrosoftNETRuntimeWebAssemblySdkVersion>7.0.0-preview.6.22323.6</MicrosoftNETRuntimeWebAssemblySdkVersion>
+ <MicrosoftNETCoreAppRuntimeAOTwinx64CrossbrowserwasmVersion>7.0.0-preview.6.22323.6</MicrosoftNETCoreAppRuntimeAOTwinx64CrossbrowserwasmVersion>
+ <MicrosoftNETCoreBrowserDebugHostTransportVersion>7.0.0-preview.6.22323.6</MicrosoftNETCoreBrowserDebugHostTransportVersion>
+ <MicrosoftExtensionsCachingAbstractionsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsCachingAbstractionsVersion>
+ <MicrosoftExtensionsCachingMemoryVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsCachingMemoryVersion>
+ <MicrosoftExtensionsConfigurationAbstractionsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationAbstractionsVersion>
+ <MicrosoftExtensionsConfigurationBinderVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationBinderVersion>
+ <MicrosoftExtensionsConfigurationCommandLineVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationCommandLineVersion>
+ <MicrosoftExtensionsConfigurationEnvironmentVariablesVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationEnvironmentVariablesVersion>
+ <MicrosoftExtensionsConfigurationFileExtensionsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationFileExtensionsVersion>
+ <MicrosoftExtensionsConfigurationIniVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationIniVersion>
+ <MicrosoftExtensionsConfigurationJsonVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationJsonVersion>
+ <MicrosoftExtensionsConfigurationVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationVersion>
+ <MicrosoftExtensionsConfigurationUserSecretsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationUserSecretsVersion>
+ <MicrosoftExtensionsConfigurationXmlVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsConfigurationXmlVersion>
+ <MicrosoftExtensionsDependencyInjectionAbstractionsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsDependencyInjectionAbstractionsVersion>
+ <MicrosoftExtensionsDependencyInjectionVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsDependencyInjectionVersion>
+ <MicrosoftExtensionsFileProvidersAbstractionsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsFileProvidersAbstractionsVersion>
+ <MicrosoftExtensionsFileProvidersCompositeVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsFileProvidersCompositeVersion>
+ <MicrosoftExtensionsFileProvidersPhysicalVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsFileProvidersPhysicalVersion>
+ <MicrosoftExtensionsFileSystemGlobbingVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsFileSystemGlobbingVersion>
+ <MicrosoftExtensionsHostFactoryResolverSourcesVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsHostFactoryResolverSourcesVersion>
+ <MicrosoftExtensionsHostingAbstractionsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsHostingAbstractionsVersion>
+ <MicrosoftExtensionsHostingVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsHostingVersion>
+ <MicrosoftExtensionsHttpVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsHttpVersion>
+ <MicrosoftExtensionsLoggingAbstractionsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsLoggingAbstractionsVersion>
+ <MicrosoftExtensionsLoggingConfigurationVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsLoggingConfigurationVersion>
+ <MicrosoftExtensionsLoggingConsoleVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsLoggingConsoleVersion>
+ <MicrosoftExtensionsLoggingDebugVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsLoggingDebugVersion>
+ <MicrosoftExtensionsLoggingEventSourceVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsLoggingEventSourceVersion>
+ <MicrosoftExtensionsLoggingEventLogVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsLoggingEventLogVersion>
+ <MicrosoftExtensionsLoggingVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsLoggingVersion>
+ <MicrosoftExtensionsLoggingTraceSourceVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsLoggingTraceSourceVersion>
+ <MicrosoftExtensionsOptionsConfigurationExtensionsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsOptionsConfigurationExtensionsVersion>
+ <MicrosoftExtensionsOptionsDataAnnotationsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsOptionsDataAnnotationsVersion>
+ <MicrosoftExtensionsOptionsVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsOptionsVersion>
+ <MicrosoftExtensionsPrimitivesVersion>7.0.0-preview.6.22323.6</MicrosoftExtensionsPrimitivesVersion>
+ <MicrosoftInternalRuntimeAspNetCoreTransportVersion>7.0.0-preview.6.22323.6</MicrosoftInternalRuntimeAspNetCoreTransportVersion>
+ <SystemConfigurationConfigurationManagerVersion>7.0.0-preview.6.22323.6</SystemConfigurationConfigurationManagerVersion>
+ <SystemDiagnosticsDiagnosticSourceVersion>7.0.0-preview.6.22323.6</SystemDiagnosticsDiagnosticSourceVersion>
+ <SystemDiagnosticsEventLogVersion>7.0.0-preview.6.22323.6</SystemDiagnosticsEventLogVersion>
+ <SystemDirectoryServicesProtocolsVersion>7.0.0-preview.6.22323.6</SystemDirectoryServicesProtocolsVersion>
+ <SystemIOPipelinesVersion>7.0.0-preview.6.22323.6</SystemIOPipelinesVersion>
+ <SystemNetHttpJsonVersion>7.0.0-preview.6.22323.6</SystemNetHttpJsonVersion>
+ <SystemNetHttpWinHttpHandlerVersion>7.0.0-preview.6.22323.6</SystemNetHttpWinHttpHandlerVersion>
+ <SystemReflectionMetadataVersion>7.0.0-preview.6.22323.6</SystemReflectionMetadataVersion>
+ <SystemResourcesExtensionsVersion>7.0.0-preview.6.22323.6</SystemResourcesExtensionsVersion>
+ <SystemSecurityCryptographyPkcsVersion>7.0.0-preview.6.22323.6</SystemSecurityCryptographyPkcsVersion>
+ <SystemSecurityCryptographyXmlVersion>7.0.0-preview.6.22323.6</SystemSecurityCryptographyXmlVersion>
+ <SystemSecurityPermissionsVersion>7.0.0-preview.6.22323.6</SystemSecurityPermissionsVersion>
+ <SystemServiceProcessServiceControllerVersion>7.0.0-preview.6.22323.6</SystemServiceProcessServiceControllerVersion>
+ <SystemTextEncodingsWebVersion>7.0.0-preview.6.22323.6</SystemTextEncodingsWebVersion>
+ <SystemTextJsonVersion>7.0.0-preview.6.22323.6</SystemTextJsonVersion>
+ <SystemThreadingAccessControlVersion>7.0.0-preview.6.22323.6</SystemThreadingAccessControlVersion>
+ <SystemThreadingChannelsVersion>7.0.0-preview.6.22323.6</SystemThreadingChannelsVersion>
+ <SystemThreadingRateLimitingVersion>7.0.0-preview.6.22323.6</SystemThreadingRateLimitingVersion>
<!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
- <MicrosoftNETCorePlatformsVersion>7.0.0-preview.6.22321.8</MicrosoftNETCorePlatformsVersion>
+ <MicrosoftNETCorePlatformsVersion>7.0.0-preview.6.22323.6</MicrosoftNETCorePlatformsVersion>
<!-- Packages from dotnet/efcore -->
- <dotnetefVersion>7.0.0-preview.6.22322.3</dotnetefVersion>
- <MicrosoftEntityFrameworkCoreInMemoryVersion>7.0.0-preview.6.22322.3</MicrosoftEntityFrameworkCoreInMemoryVersion>
- <MicrosoftEntityFrameworkCoreRelationalVersion>7.0.0-preview.6.22322.3</MicrosoftEntityFrameworkCoreRelationalVersion>
- <MicrosoftEntityFrameworkCoreSqliteVersion>7.0.0-preview.6.22322.3</MicrosoftEntityFrameworkCoreSqliteVersion>
- <MicrosoftEntityFrameworkCoreSqlServerVersion>7.0.0-preview.6.22322.3</MicrosoftEntityFrameworkCoreSqlServerVersion>
- <MicrosoftEntityFrameworkCoreToolsVersion>7.0.0-preview.6.22322.3</MicrosoftEntityFrameworkCoreToolsVersion>
- <MicrosoftEntityFrameworkCoreVersion>7.0.0-preview.6.22322.3</MicrosoftEntityFrameworkCoreVersion>
- <MicrosoftEntityFrameworkCoreDesignVersion>7.0.0-preview.6.22322.3</MicrosoftEntityFrameworkCoreDesignVersion>
+ <dotnetefVersion>7.0.0-preview.6.22323.4</dotnetefVersion>
+ <MicrosoftEntityFrameworkCoreInMemoryVersion>7.0.0-preview.6.22323.4</MicrosoftEntityFrameworkCoreInMemoryVersion>
+ <MicrosoftEntityFrameworkCoreRelationalVersion>7.0.0-preview.6.22323.4</MicrosoftEntityFrameworkCoreRelationalVersion>
+ <MicrosoftEntityFrameworkCoreSqliteVersion>7.0.0-preview.6.22323.4</MicrosoftEntityFrameworkCoreSqliteVersion>
+ <MicrosoftEntityFrameworkCoreSqlServerVersion>7.0.0-preview.6.22323.4</MicrosoftEntityFrameworkCoreSqlServerVersion>
+ <MicrosoftEntityFrameworkCoreToolsVersion>7.0.0-preview.6.22323.4</MicrosoftEntityFrameworkCoreToolsVersion>
+ <MicrosoftEntityFrameworkCoreVersion>7.0.0-preview.6.22323.4</MicrosoftEntityFrameworkCoreVersion>
+ <MicrosoftEntityFrameworkCoreDesignVersion>7.0.0-preview.6.22323.4</MicrosoftEntityFrameworkCoreDesignVersion>
<!-- Packages from dotnet/arcade -->
<MicrosoftDotNetBuildTasksInstallersVersion>7.0.0-beta.22316.2</MicrosoftDotNetBuildTasksInstallersVersion>
<MicrosoftDotNetBuildTasksTemplatingVersion>7.0.0-beta.22316.2</MicrosoftDotNetBuildTasksTemplatingVersion>
@@ -195,6 +197,10 @@
-->
<MicrosoftNETTestSdkVersion>17.1.0-preview-20211109-03</MicrosoftNETTestSdkVersion>
<!--
+ Use a compiler new enough to use required keyword
+ -->
+ <MicrosoftNetCompilersToolsetVersion>4.4.0-1.22315.13</MicrosoftNetCompilersToolsetVersion>
+ <!--
Versions of Microsoft.CodeAnalysis packages referenced by analyzers shipped in the SDK.
This need to be pinned since they're used in 3.1 apps and need to be loadable in VS 2019.
-->
diff --git a/src/Middleware/OutputCaching/test/MemoryOutputCacheStoreTests.cs b/src/Middleware/OutputCaching/test/MemoryOutputCacheStoreTests.cs
index 1b1158c662..c3a8d48388 100644
--- a/src/Middleware/OutputCaching/test/MemoryOutputCacheStoreTests.cs
+++ b/src/Middleware/OutputCaching/test/MemoryOutputCacheStoreTests.cs
@@ -16,7 +16,7 @@ public class MemoryOutputCacheStoreTests
public async Task StoreAndGetValue_Succeeds()
{
var store = new MemoryOutputCacheStore(new MemoryCache(new MemoryCacheOptions()));
- var value = "abc"u8;
+ var value = "abc"u8.ToArray();
var key = "abc";
await store.SetAsync(key, value, null, TimeSpan.FromMinutes(1), default);
@@ -31,7 +31,7 @@ public class MemoryOutputCacheStoreTests
{
var testClock = new TestMemoryOptionsClock { UtcNow = DateTimeOffset.UtcNow };
var store = new MemoryOutputCacheStore(new MemoryCache(new MemoryCacheOptions { Clock = testClock }));
- var value = "abc"u8;
+ var value = "abc"u8.ToArray();
var key = "abc";
await store.SetAsync(key, value, null, TimeSpan.FromMilliseconds(5), default);
@@ -46,7 +46,7 @@ public class MemoryOutputCacheStoreTests
public async Task StoreNullKey_ThrowsException()
{
var store = new MemoryOutputCacheStore(new MemoryCache(new MemoryCacheOptions()));
- var value = "abc"u8;
+ var value = "abc"u8.ToArray();
string key = null;
_ = await Assert.ThrowsAsync<ArgumentNullException>("key", () => store.SetAsync(key, value, null, TimeSpan.FromMilliseconds(5), default).AsTask());
@@ -67,7 +67,7 @@ public class MemoryOutputCacheStoreTests
{
var testClock = new TestMemoryOptionsClock { UtcNow = DateTimeOffset.UtcNow };
var store = new MemoryOutputCacheStore(new MemoryCache(new MemoryCacheOptions { Clock = testClock }));
- var value = "abc"u8;
+ var value = "abc"u8.ToArray();
var key = "abc";
var tags = new string[] { "tag1" };
@@ -83,7 +83,7 @@ public class MemoryOutputCacheStoreTests
{
var testClock = new TestMemoryOptionsClock { UtcNow = DateTimeOffset.UtcNow };
var store = new MemoryOutputCacheStore(new MemoryCache(new MemoryCacheOptions { Clock = testClock }));
- var value = "abc"u8;
+ var value = "abc"u8.ToArray();
var key1 = "abc";
var key2 = "def";
var tags = new string[] { "tag1" };
@@ -103,7 +103,7 @@ public class MemoryOutputCacheStoreTests
{
var testClock = new TestMemoryOptionsClock { UtcNow = DateTimeOffset.UtcNow };
var store = new MemoryOutputCacheStore(new MemoryCache(new MemoryCacheOptions { Clock = testClock }));
- var value = "abc"u8;
+ var value = "abc"u8.ToArray();
var key = "abc";
var tags = new string[] { "tag1", "tag2" };
@@ -119,7 +119,7 @@ public class MemoryOutputCacheStoreTests
{
var testClock = new TestMemoryOptionsClock { UtcNow = DateTimeOffset.UtcNow };
var store = new MemoryOutputCacheStore(new MemoryCache(new MemoryCacheOptions { Clock = testClock }));
- var value = "abc"u8;
+ var value = "abc"u8.ToArray();
var key1 = "abc";
var key2 = "def";
var tags1 = new string[] { "tag1", "tag2" };
diff --git a/src/Middleware/OutputCaching/test/OutputCacheEntryFormatterTests.cs b/src/Middleware/OutputCaching/test/OutputCacheEntryFormatterTests.cs
index e6610141b2..a0de533fc0 100644
--- a/src/Middleware/OutputCaching/test/OutputCacheEntryFormatterTests.cs
+++ b/src/Middleware/OutputCaching/test/OutputCacheEntryFormatterTests.cs
@@ -38,7 +38,7 @@ public class OutputCacheEntryFormatterTests
var key = "abc";
var entry = new OutputCacheEntry()
{
- Body = new CachedResponseBody(new List<byte[]>() { "lorem"u8, "ipsum"u8 }, 10),
+ Body = new CachedResponseBody(new List<byte[]>() { "lorem"u8.ToArray(), "ipsum"u8.ToArray() }, 10),
Created = DateTimeOffset.UtcNow,
Headers = new HeaderDictionary { [HeaderNames.Accept] = "text/plain", [HeaderNames.AcceptCharset] = "utf8" },
StatusCode = StatusCodes.Status201Created,
diff --git a/src/Middleware/RateLimiting/src/DefaultCombinedLease.cs b/src/Middleware/RateLimiting/src/DefaultCombinedLease.cs
new file mode 100644
index 0000000000..3fb05bae64
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/DefaultCombinedLease.cs
@@ -0,0 +1,98 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.RateLimiting;
+
+namespace Microsoft.AspNetCore.RateLimiting;
+
+internal sealed class DefaultCombinedLease : RateLimitLease
+{
+ private readonly RateLimitLease? _globalLease;
+ private readonly RateLimitLease _endpointLease;
+ private HashSet<string>? _metadataNames;
+
+ public DefaultCombinedLease(RateLimitLease? globalLease, RateLimitLease endpointLease)
+ {
+ _globalLease = globalLease;
+ _endpointLease = endpointLease;
+ }
+
+ public override bool IsAcquired => true;
+
+ public override IEnumerable<string> MetadataNames
+ {
+ get
+ {
+ if (_metadataNames is null)
+ {
+ _metadataNames = new HashSet<string>();
+ if (_globalLease is not null)
+ {
+ foreach (string metadataName in _globalLease.MetadataNames)
+ {
+ _metadataNames.Add(metadataName);
+ }
+ }
+ foreach (string metadataName in _endpointLease.MetadataNames)
+ {
+ _metadataNames.Add(metadataName);
+ }
+ }
+ return _metadataNames;
+ }
+ }
+
+ public override bool TryGetMetadata(string metadataName, out object? metadata)
+ {
+ // Use the first metadata item of a given name, ignore duplicates, we can't reliably merge arbitrary metadata
+ // Creating an object[] if there are multiple of the same metadataName could work, but makes consumption of metadata messy
+ // and makes MetadataName.Create<T>(...) uses no longer work
+ if (_endpointLease.TryGetMetadata(metadataName, out metadata))
+ {
+ return true;
+ }
+ if (_globalLease is not null)
+ {
+ if (_globalLease.TryGetMetadata(metadataName, out metadata))
+ {
+ return true;
+ }
+ }
+
+ metadata = null;
+ return false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ List<Exception>? exceptions = null;
+
+ // Dispose endpoint lease first, then global lease (reverse order of when they were acquired)
+ // Avoids issues where dispose might unblock a queued acquire and then the acquire fails when acquiring the next limiter.
+ // When disposing in reverse order there wont be any issues of unblocking an acquire that affects acquires on limiters in the chain after it
+ try
+ {
+ _endpointLease.Dispose();
+ }
+ catch (Exception ex)
+ {
+ exceptions ??= new List<Exception>();
+ exceptions.Add(ex);
+ }
+
+ try
+ {
+ _globalLease?.Dispose();
+ }
+ catch (Exception ex)
+ {
+ exceptions ??= new List<Exception>();
+ exceptions.Add(ex);
+ }
+
+ if (exceptions is not null)
+ {
+ throw new AggregateException(exceptions);
+ }
+ }
+}
diff --git a/src/Middleware/RateLimiting/src/DefaultKeyType.T.cs b/src/Middleware/RateLimiting/src/DefaultKeyType.T.cs
new file mode 100644
index 0000000000..1718794021
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/DefaultKeyType.T.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.RateLimiting;
+
+internal sealed class DefaultKeyType<TKey>: DefaultKeyType
+{
+ private readonly TKey _key;
+
+ public DefaultKeyType(TKey key)
+ {
+ _key = key;
+ }
+
+ public override object? GetKey()
+ {
+ return _key;
+ }
+}
diff --git a/src/Middleware/RateLimiting/src/DefaultKeyType.cs b/src/Middleware/RateLimiting/src/DefaultKeyType.cs
new file mode 100644
index 0000000000..6ca39099c9
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/DefaultKeyType.cs
@@ -0,0 +1,9 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.RateLimiting;
+
+internal abstract class DefaultKeyType
+{
+ public abstract object? GetKey();
+}
diff --git a/src/Middleware/RateLimiting/src/DefaultKeyTypeEqualityComparer.cs b/src/Middleware/RateLimiting/src/DefaultKeyTypeEqualityComparer.cs
new file mode 100644
index 0000000000..c2e63f4700
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/DefaultKeyTypeEqualityComparer.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.AspNetCore.RateLimiting;
+internal class DefaultKeyTypeEqualityComparer : IEqualityComparer<DefaultKeyType>
+{
+ public bool Equals(DefaultKeyType? x, DefaultKeyType? y)
+ {
+ if (x == null && y == null)
+ {
+ return true;
+ }
+ else if (x == null || y == null)
+ {
+ return false;
+ }
+
+ var xKey = x.GetKey();
+ var yKey = y.GetKey();
+ if (xKey == null && yKey == null)
+ {
+ return true;
+ }
+ else if (xKey == null || yKey == null)
+ {
+ return false;
+ }
+
+ return xKey.Equals(yKey);
+ }
+
+ public int GetHashCode([DisallowNull] DefaultKeyType obj)
+ {
+ var key = obj.GetKey();
+ if (key is not null)
+ {
+ return key.GetHashCode();
+ }
+ // REVIEW - is this reasonable?
+ return default;
+ }
+}
diff --git a/src/Middleware/RateLimiting/src/DefaultRateLimiterPolicy.cs b/src/Middleware/RateLimiting/src/DefaultRateLimiterPolicy.cs
new file mode 100644
index 0000000000..7a32df215f
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/DefaultRateLimiterPolicy.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.RateLimiting;
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.RateLimiting;
+internal sealed class DefaultRateLimiterPolicy : IRateLimiterPolicy<DefaultKeyType>
+{
+ private readonly Func<HttpContext, RateLimitPartition<DefaultKeyType>> _partitioner;
+ private readonly Func<OnRejectedContext, CancellationToken, ValueTask>? _onRejected;
+
+ public DefaultRateLimiterPolicy(Func<HttpContext, RateLimitPartition<DefaultKeyType>> partitioner, Func<OnRejectedContext, CancellationToken, ValueTask>? onRejected)
+ {
+ _partitioner = partitioner;
+ _onRejected = onRejected;
+ }
+
+ public Func<OnRejectedContext, CancellationToken, ValueTask>? OnRejected => _onRejected;
+
+ public RateLimitPartition<DefaultKeyType> GetPartition(HttpContext httpContext)
+ {
+ return _partitioner(httpContext);
+ }
+}
diff --git a/src/Middleware/RateLimiting/src/IRateLimiterMetadata.cs b/src/Middleware/RateLimiting/src/IRateLimiterMetadata.cs
new file mode 100644
index 0000000000..6cb096d4ff
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/IRateLimiterMetadata.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.RateLimiting;
+
+/// <summary>
+/// An interface which can be used to identify a type which provides metadata needed for enabling request rate limiting support.
+/// </summary>
+internal interface IRateLimiterMetadata
+{
+ /// <summary>
+ /// The name of the limiter which needs to be applied.
+ /// </summary>
+ string PolicyName { get; }
+}
diff --git a/src/Middleware/RateLimiting/src/IRateLimiterPolicy.cs b/src/Middleware/RateLimiting/src/IRateLimiterPolicy.cs
new file mode 100644
index 0000000000..7487253858
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/IRateLimiterPolicy.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.RateLimiting;
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.RateLimiting;
+
+/// <summary>
+/// An interface which is used to represent a RateLimiter policy.
+/// </summary>
+public interface IRateLimiterPolicy<TPartitionKey>
+{
+ /// <summary>
+ /// Gets the <see cref="Func{OnRejectedContext, CancellationToken, ValueTask}"/> that handles requests rejected by this middleware.
+ /// </summary>
+ Func<OnRejectedContext, CancellationToken, ValueTask>? OnRejected { get; }
+
+ /// <summary>
+ /// Gets the <see cref="RateLimitPartition{TPartitionKey}"/> that applies to the given <see cref="HttpContext"/>.
+ /// </summary>
+ /// <param name="httpContext">The <see cref="HttpContext"/> to get the partition for.</param>
+ RateLimitPartition<TPartitionKey> GetPartition(HttpContext httpContext);
+}
diff --git a/src/Middleware/RateLimiting/src/LeaseContext.cs b/src/Middleware/RateLimiting/src/LeaseContext.cs
new file mode 100644
index 0000000000..5a508b245d
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/LeaseContext.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.RateLimiting;
+
+namespace Microsoft.AspNetCore.RateLimiting;
+internal struct LeaseContext : IDisposable
+{
+ public bool? GlobalRejected { get; init; }
+
+ public required RateLimitLease Lease { get; init; }
+
+ public void Dispose()
+ {
+ Lease.Dispose();
+ }
+}
diff --git a/src/Middleware/RateLimiting/src/NoLimiter.cs b/src/Middleware/RateLimiting/src/NoLimiter.cs
deleted file mode 100644
index e663b1f160..0000000000
--- a/src/Middleware/RateLimiting/src/NoLimiter.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Threading.RateLimiting;
-
-namespace Microsoft.AspNetCore.RateLimiting;
-internal sealed class NoLimiter<TResource> : PartitionedRateLimiter<TResource>
-{
- public override int GetAvailablePermits(TResource resourceID)
- {
- return 1;
- }
-
- protected override RateLimitLease AcquireCore(TResource resourceID, int permitCount)
- {
- return new NoLimiterLease();
- }
-
- protected override ValueTask<RateLimitLease> WaitAsyncCore(TResource resourceID, int permitCount, CancellationToken cancellationToken)
- {
- return new ValueTask<RateLimitLease>(new NoLimiterLease());
- }
-}
-
-internal sealed class NoLimiterLease : RateLimitLease
-{
- public override bool IsAcquired => true;
-
- public override IEnumerable<string> MetadataNames => new List<string>();
-
- public override bool TryGetMetadata(string metadataName, out object? metadata)
- {
- metadata = null;
- return false;
- }
-}
diff --git a/src/Middleware/RateLimiting/src/OnRejectedContext.cs b/src/Middleware/RateLimiting/src/OnRejectedContext.cs
new file mode 100644
index 0000000000..0570955568
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/OnRejectedContext.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.RateLimiting;
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.RateLimiting;
+
+/// <summary>
+/// Holds state needed for the OnRejected callback in the RateLimitingMiddleware.
+/// </summary>
+public sealed class OnRejectedContext
+{
+ /// <summary>
+ /// Gets or sets the <see cref="HttpContext"/> that the OnRejected callback will have access to
+ /// </summary>
+ public required HttpContext HttpContext { get; init; }
+
+ /// <summary>
+ /// Gets or sets the failed <see cref="RateLimitLease"/> that the OnRejected callback will have access to
+ /// </summary>
+ public required RateLimitLease Lease { get; init; }
+}
diff --git a/src/Middleware/RateLimiting/src/PolicyNameKey.cs b/src/Middleware/RateLimiting/src/PolicyNameKey.cs
new file mode 100644
index 0000000000..bc34d23129
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/PolicyNameKey.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.RateLimiting;
+internal sealed class PolicyNameKey
+{
+ public required string PolicyName { get; init; }
+
+ public override bool Equals(object? obj)
+ {
+ if (obj is PolicyNameKey key)
+ {
+ return PolicyName.Equals(key.PolicyName);
+ }
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return PolicyName.GetHashCode();
+ }
+}
diff --git a/src/Middleware/RateLimiting/src/PolicyTypeInfo.cs b/src/Middleware/RateLimiting/src/PolicyTypeInfo.cs
new file mode 100644
index 0000000000..f71aa1302a
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/PolicyTypeInfo.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.AspNetCore.RateLimiting;
+internal sealed class PolicyTypeInfo
+{
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ public required Type PolicyType { get; init; }
+ public required Type PartitionKeyType { get; init; }
+}
diff --git a/src/Middleware/RateLimiting/src/PublicAPI.Unshipped.txt b/src/Middleware/RateLimiting/src/PublicAPI.Unshipped.txt
index b62cec89b1..3bbcc5cb4c 100644
--- a/src/Middleware/RateLimiting/src/PublicAPI.Unshipped.txt
+++ b/src/Middleware/RateLimiting/src/PublicAPI.Unshipped.txt
@@ -1,11 +1,31 @@
+Microsoft.AspNetCore.Builder.RateLimiterApplicationBuilderExtensions
+Microsoft.AspNetCore.Builder.RateLimiterEndpointConventionBuilderExtensions
+Microsoft.AspNetCore.RateLimiting.IRateLimiterPolicy<TPartitionKey>
+Microsoft.AspNetCore.RateLimiting.IRateLimiterPolicy<TPartitionKey>.GetPartition(Microsoft.AspNetCore.Http.HttpContext! httpContext) -> System.Threading.RateLimiting.RateLimitPartition<TPartitionKey>
+Microsoft.AspNetCore.RateLimiting.IRateLimiterPolicy<TPartitionKey>.OnRejected.get -> System.Func<Microsoft.AspNetCore.RateLimiting.OnRejectedContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>?
+Microsoft.AspNetCore.RateLimiting.OnRejectedContext
+Microsoft.AspNetCore.RateLimiting.OnRejectedContext.HttpContext.get -> Microsoft.AspNetCore.Http.HttpContext!
+Microsoft.AspNetCore.RateLimiting.OnRejectedContext.HttpContext.init -> void
+Microsoft.AspNetCore.RateLimiting.OnRejectedContext.Lease.get -> System.Threading.RateLimiting.RateLimitLease!
+Microsoft.AspNetCore.RateLimiting.OnRejectedContext.Lease.init -> void
+Microsoft.AspNetCore.RateLimiting.OnRejectedContext.OnRejectedContext() -> void
Microsoft.AspNetCore.RateLimiting.RateLimiterOptions
-Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.DefaultRejectionStatusCode.get -> int
-Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.DefaultRejectionStatusCode.set -> void
-Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.Limiter.get -> System.Threading.RateLimiting.PartitionedRateLimiter<Microsoft.AspNetCore.Http.HttpContext!>!
-Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.Limiter.set -> void
-Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.OnRejected.get -> System.Func<Microsoft.AspNetCore.Http.HttpContext!, System.Threading.RateLimiting.RateLimitLease!, System.Threading.Tasks.Task!>!
+Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.AddPolicy<TPartitionKey, TPolicy>(string! policyName) -> Microsoft.AspNetCore.RateLimiting.RateLimiterOptions!
+Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.AddPolicy<TPartitionKey>(string! policyName, Microsoft.AspNetCore.RateLimiting.IRateLimiterPolicy<TPartitionKey>! policy) -> Microsoft.AspNetCore.RateLimiting.RateLimiterOptions!
+Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.AddPolicy<TPartitionKey>(string! policyName, System.Func<Microsoft.AspNetCore.Http.HttpContext!, System.Threading.RateLimiting.RateLimitPartition<TPartitionKey>>! partitioner) -> Microsoft.AspNetCore.RateLimiting.RateLimiterOptions!
+Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.GlobalLimiter.get -> System.Threading.RateLimiting.PartitionedRateLimiter<Microsoft.AspNetCore.Http.HttpContext!>?
+Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.GlobalLimiter.set -> void
+Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.OnRejected.get -> System.Func<Microsoft.AspNetCore.RateLimiting.OnRejectedContext!, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask>?
Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.OnRejected.set -> void
Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.RateLimiterOptions() -> void
-Microsoft.AspNetCore.RateLimiting.RateLimitingApplicationBuilderExtensions
-static Microsoft.AspNetCore.RateLimiting.RateLimitingApplicationBuilderExtensions.UseRateLimiter(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app) -> Microsoft.AspNetCore.Builder.IApplicationBuilder!
-static Microsoft.AspNetCore.RateLimiting.RateLimitingApplicationBuilderExtensions.UseRateLimiter(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, Microsoft.AspNetCore.RateLimiting.RateLimiterOptions! options) -> Microsoft.AspNetCore.Builder.IApplicationBuilder!
+Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.RejectionStatusCode.get -> int
+Microsoft.AspNetCore.RateLimiting.RateLimiterOptions.RejectionStatusCode.set -> void
+Microsoft.AspNetCore.RateLimiting.RateLimiterOptionsExtensions
+static Microsoft.AspNetCore.Builder.RateLimiterApplicationBuilderExtensions.UseRateLimiter(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app) -> Microsoft.AspNetCore.Builder.IApplicationBuilder!
+static Microsoft.AspNetCore.Builder.RateLimiterApplicationBuilderExtensions.UseRateLimiter(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, Microsoft.AspNetCore.RateLimiting.RateLimiterOptions! options) -> Microsoft.AspNetCore.Builder.IApplicationBuilder!
+static Microsoft.AspNetCore.Builder.RateLimiterEndpointConventionBuilderExtensions.RequireRateLimiting<TBuilder>(this TBuilder builder, string! policyName) -> TBuilder
+static Microsoft.AspNetCore.RateLimiting.RateLimiterOptionsExtensions.AddConcurrencyLimiter(this Microsoft.AspNetCore.RateLimiting.RateLimiterOptions! options, string! policyName, System.Threading.RateLimiting.ConcurrencyLimiterOptions! concurrencyLimiterOptions) -> Microsoft.AspNetCore.RateLimiting.RateLimiterOptions!
+static Microsoft.AspNetCore.RateLimiting.RateLimiterOptionsExtensions.AddFixedWindowLimiter(this Microsoft.AspNetCore.RateLimiting.RateLimiterOptions! options, string! policyName, System.Threading.RateLimiting.FixedWindowRateLimiterOptions! fixedWindowRateLimiterOptions) -> Microsoft.AspNetCore.RateLimiting.RateLimiterOptions!
+static Microsoft.AspNetCore.RateLimiting.RateLimiterOptionsExtensions.AddNoLimiter(this Microsoft.AspNetCore.RateLimiting.RateLimiterOptions! options, string! policyName) -> Microsoft.AspNetCore.RateLimiting.RateLimiterOptions!
+static Microsoft.AspNetCore.RateLimiting.RateLimiterOptionsExtensions.AddSlidingWindowLimiter(this Microsoft.AspNetCore.RateLimiting.RateLimiterOptions! options, string! policyName, System.Threading.RateLimiting.SlidingWindowRateLimiterOptions! slidingWindowRateLimiterOptions) -> Microsoft.AspNetCore.RateLimiting.RateLimiterOptions!
+static Microsoft.AspNetCore.RateLimiting.RateLimiterOptionsExtensions.AddTokenBucketLimiter(this Microsoft.AspNetCore.RateLimiting.RateLimiterOptions! options, string! policyName, System.Threading.RateLimiting.TokenBucketRateLimiterOptions! tokenBucketRateLimiterOptions) -> Microsoft.AspNetCore.RateLimiting.RateLimiterOptions!
diff --git a/src/Middleware/RateLimiting/src/RateLimitingApplicationBuilderExtensions.cs b/src/Middleware/RateLimiting/src/RateLimiterApplicationBuilderExtensions.cs
index 64dddf417d..cd1ec7b826 100644
--- a/src/Middleware/RateLimiting/src/RateLimitingApplicationBuilderExtensions.cs
+++ b/src/Middleware/RateLimiting/src/RateLimiterApplicationBuilderExtensions.cs
@@ -1,15 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.RateLimiting;
using Microsoft.Extensions.Options;
-namespace Microsoft.AspNetCore.RateLimiting;
+namespace Microsoft.AspNetCore.Builder;
/// <summary>
/// Extension methods for the RateLimiting middleware.
/// </summary>
-public static class RateLimitingApplicationBuilderExtensions
+public static class RateLimiterApplicationBuilderExtensions
{
/// <summary>
/// Enables rate limiting for the application.
diff --git a/src/Middleware/RateLimiting/src/RateLimiterEndpointConventionBuilderExtensions.cs b/src/Middleware/RateLimiting/src/RateLimiterEndpointConventionBuilderExtensions.cs
new file mode 100644
index 0000000000..27096dfd7a
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/RateLimiterEndpointConventionBuilderExtensions.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.AspNetCore.RateLimiting;
+
+namespace Microsoft.AspNetCore.Builder;
+
+/// <summary>
+/// Rate limiter extension methods for <see cref="IEndpointConventionBuilder"/>.
+/// </summary>
+public static class RateLimiterEndpointConventionBuilderExtensions
+{
+ /// <summary>
+ /// Adds the specified rate limiter to the endpoint(s).
+ /// </summary>
+ /// <param name="builder">The endpoint convention builder.</param>
+ /// <param name="policyName">The name of the rate limiter to add to the endpoint.</param>
+ /// <returns>The original convention builder parameter.</returns>
+ public static TBuilder RequireRateLimiting<TBuilder>(this TBuilder builder, string policyName) where TBuilder : IEndpointConventionBuilder
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ if (policyName == null)
+ {
+ throw new ArgumentNullException(nameof(policyName));
+ }
+
+ builder.Add(endpointBuilder =>
+ {
+ endpointBuilder.Metadata.Add(new RateLimiterMetadata(policyName));
+ });
+
+ return builder;
+ }
+}
diff --git a/src/Middleware/RateLimiting/src/RateLimiterMetadata.cs b/src/Middleware/RateLimiting/src/RateLimiterMetadata.cs
new file mode 100644
index 0000000000..31acb7ce82
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/RateLimiterMetadata.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.AspNetCore.RateLimiting;
+
+/// <summary>
+/// Metadata that provides endpoint-specific request rate limiting.
+/// </summary>
+internal class RateLimiterMetadata : IRateLimiterMetadata
+{
+ /// <summary>
+ /// Creates a new instance of <see cref="RateLimiterMetadata"/> using the specified limiter.
+ /// </summary>
+ /// <param name="policyName">The name of the limiter which needs to be applied.</param>
+ public RateLimiterMetadata(string policyName)
+ {
+ PolicyName = policyName;
+ }
+
+ /// <summary>
+ /// The name of the limiter which needs to be applied.
+ /// </summary>
+ public string PolicyName { get; }
+}
diff --git a/src/Middleware/RateLimiting/src/RateLimiterOptions.cs b/src/Middleware/RateLimiting/src/RateLimiterOptions.cs
index bc1ab30b7a..d232e93bac 100644
--- a/src/Middleware/RateLimiting/src/RateLimiterOptions.cs
+++ b/src/Middleware/RateLimiting/src/RateLimiterOptions.cs
@@ -1,8 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Threading.RateLimiting;
using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.RateLimiting;
@@ -11,30 +13,22 @@ namespace Microsoft.AspNetCore.RateLimiting;
/// </summary>
public sealed class RateLimiterOptions
{
- // TODO - Provide a default?
- private PartitionedRateLimiter<HttpContext> _limiter = new NoLimiter<HttpContext>();
- private Func<HttpContext, RateLimitLease, Task> _onRejected = (context, lease) =>
- {
- return Task.CompletedTask;
- };
+ internal IDictionary<string, DefaultRateLimiterPolicy> PolicyMap { get; }
+ = new Dictionary<string, DefaultRateLimiterPolicy>(StringComparer.Ordinal);
+
+ internal IDictionary<string, Func<IServiceProvider, DefaultRateLimiterPolicy>> UnactivatedPolicyMap { get; }
+ = new Dictionary<string, Func<IServiceProvider, DefaultRateLimiterPolicy>>(StringComparer.Ordinal);
/// <summary>
- /// Gets or sets the <see cref="PartitionedRateLimiter{TResource}"/>
+ /// Gets or sets the global <see cref="PartitionedRateLimiter{HttpContext}"/> that will be applied on all requests.
+ /// The global limiter will be executed first, followed by the endpoint-specific limiter, if one exists.
/// </summary>
- public PartitionedRateLimiter<HttpContext> Limiter
- {
- get => _limiter;
- set => _limiter = value ?? throw new ArgumentNullException(nameof(value));
- }
+ public PartitionedRateLimiter<HttpContext>? GlobalLimiter { get; set; }
/// <summary>
- /// Gets or sets a <see cref="Func{HttpContext, RateLimitLease, Task}"/> that handles requests rejected by this middleware.
+ /// Gets or sets a <see cref="Func{OnRejectedContext, CancellationToken, ValueTask}"/> that handles requests rejected by this middleware.
/// </summary>
- public Func<HttpContext, RateLimitLease, Task> OnRejected
- {
- get => _onRejected;
- set => _onRejected = value ?? throw new ArgumentNullException(nameof(value));
- }
+ public Func<OnRejectedContext, CancellationToken, ValueTask>? OnRejected { get; set; }
/// <summary>
/// Gets or sets the default status code to set on the response when a request is rejected.
@@ -44,5 +38,108 @@ public sealed class RateLimiterOptions
/// This status code will be set before <see cref="OnRejected"/> is called, so any status code set by
/// <see cref="OnRejected"/> will "win" over this default.
/// </remarks>
- public int DefaultRejectionStatusCode { get; set; } = StatusCodes.Status503ServiceUnavailable;
+ public int RejectionStatusCode { get; set; } = StatusCodes.Status503ServiceUnavailable;
+
+ /// <summary>
+ /// Adds a new rate limiting policy with the given policyName.
+ /// </summary>
+ /// <param name="policyName">The name to be associated with the given <see cref="RateLimiter"/>.</param>
+ /// <param name="partitioner">Method called every time an Acquire or WaitAsync call is made to figure out what rate limiter to apply to the request.</param>
+ public RateLimiterOptions AddPolicy<TPartitionKey>(string policyName, Func<HttpContext, RateLimitPartition<TPartitionKey>> partitioner)
+ {
+ ArgumentNullException.ThrowIfNull(policyName);
+ ArgumentNullException.ThrowIfNull(partitioner);
+
+ if (PolicyMap.ContainsKey(policyName) || UnactivatedPolicyMap.ContainsKey(policyName))
+ {
+ throw new ArgumentException($"There already exists a policy with the name {policyName}");
+ }
+
+ PolicyMap.Add(policyName, new DefaultRateLimiterPolicy(ConvertPartitioner<TPartitionKey>(partitioner), null));
+
+ return this;
+ }
+
+ /// <summary>
+ /// Adds a new rate limiting policy with the given policyName.
+ /// </summary>
+ /// <param name="policyName">The name to be associated with the given TPolicy.</param>
+ public RateLimiterOptions AddPolicy<TPartitionKey, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TPolicy>(string policyName) where TPolicy : IRateLimiterPolicy<TPartitionKey>
+ {
+ ArgumentNullException.ThrowIfNull(policyName);
+
+ if (PolicyMap.ContainsKey(policyName) || UnactivatedPolicyMap.ContainsKey(policyName))
+ {
+ throw new ArgumentException($"There already exists a policy with the name {policyName}");
+ }
+
+ var policyType = new PolicyTypeState(typeof(TPolicy));
+ Func <IServiceProvider, DefaultRateLimiterPolicy> policyFunc = serviceProvider =>
+ {
+ var instance = (IRateLimiterPolicy<TPartitionKey>)ActivatorUtilities.CreateInstance(serviceProvider, policyType.PolicyType);
+ return new DefaultRateLimiterPolicy(ConvertPartitioner<TPartitionKey>(instance.GetPartition), instance.OnRejected);
+ };
+
+ UnactivatedPolicyMap.Add(policyName, policyFunc);
+
+ return this;
+ }
+
+ /// <summary>
+ /// Adds a new rate limiting policy with the given policyName.
+ /// </summary>
+ /// <param name="policyName">The name to be associated with the given <see cref="IRateLimiterPolicy{TPartitionKey}"/>.</param>
+ /// <param name="policy">The <see cref="IRateLimiterPolicy{TPartitionKey}"/> to be applied.</param>
+ public RateLimiterOptions AddPolicy<TPartitionKey>(string policyName, IRateLimiterPolicy<TPartitionKey> policy)
+ {
+ ArgumentNullException.ThrowIfNull(policyName);
+
+ if (PolicyMap.ContainsKey(policyName) || UnactivatedPolicyMap.ContainsKey(policyName))
+ {
+ throw new ArgumentException($"There already exists a policy with the name {policyName}");
+ }
+
+ ArgumentNullException.ThrowIfNull(policy);
+
+ PolicyMap.Add(policyName, new DefaultRateLimiterPolicy(ConvertPartitioner<TPartitionKey>(policy.GetPartition), policy.OnRejected));
+
+ return this;
+ }
+
+ internal RateLimiterOptions InternalAddPolicy(string policyName, Func<HttpContext, RateLimitPartition<DefaultKeyType>> partitioner)
+ {
+ ArgumentNullException.ThrowIfNull(policyName);
+ ArgumentNullException.ThrowIfNull(partitioner);
+
+ if (PolicyMap.ContainsKey(policyName) || UnactivatedPolicyMap.ContainsKey(policyName))
+ {
+ throw new ArgumentException($"There already exists a policy with the name {policyName}");
+ }
+
+ PolicyMap.Add(policyName, new DefaultRateLimiterPolicy(partitioner, null));
+
+ return this;
+ }
+
+ // Converts a Partition<TKey> to a Partition<DefaultKeyType<TKey>> to prevent accidental collisions with the keys we create in the the RateLimiterOptionsExtensions.
+ private static Func<HttpContext, RateLimitPartition<DefaultKeyType>> ConvertPartitioner<TPartitionKey>(Func<HttpContext, RateLimitPartition<TPartitionKey>> partitioner)
+ {
+ return (context =>
+ {
+ RateLimitPartition<TPartitionKey> partition = partitioner(context);
+ return new RateLimitPartition<DefaultKeyType>(new DefaultKeyType<TPartitionKey>(partition.PartitionKey), key => partition.Factory(partition.PartitionKey));
+ });
+ }
+
+ // Workaround for linker bug: https://github.com/dotnet/linker/issues/1981
+ private readonly struct PolicyTypeState
+ {
+ public PolicyTypeState([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type policyType)
+ {
+ PolicyType = policyType;
+ }
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
+ public Type PolicyType { get; }
+ }
}
diff --git a/src/Middleware/RateLimiting/src/RateLimiterOptionsExtensions.cs b/src/Middleware/RateLimiting/src/RateLimiterOptionsExtensions.cs
new file mode 100644
index 0000000000..4d8c26cc35
--- /dev/null
+++ b/src/Middleware/RateLimiting/src/RateLimiterOptionsExtensions.cs
@@ -0,0 +1,90 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.RateLimiting;
+
+namespace Microsoft.AspNetCore.RateLimiting;
+
+/// <summary>
+/// Extension methods for the RateLimiting middleware options.
+/// </summary>
+public static class RateLimiterOptionsExtensions
+{
+ /// <summary>
+ /// Adds a new <see cref="TokenBucketRateLimiter"/> with the given <see cref="TokenBucketRateLimiterOptions"/> to the <see cref="RateLimiterOptions"/>.
+ /// </summary>
+ /// <param name="options">The <see cref="RateLimiterOptions"/> to add a limiter to.</param>
+ /// <param name="policyName">The name that will be associated with the limiter.</param>
+ /// <param name="tokenBucketRateLimiterOptions">The <see cref="TokenBucketRateLimiterOptions"/> to be used for the limiter.</param>
+ /// <returns>This <see cref="RateLimiterOptions"/>.</returns>
+ public static RateLimiterOptions AddTokenBucketLimiter(this RateLimiterOptions options, string policyName, TokenBucketRateLimiterOptions tokenBucketRateLimiterOptions)
+ {
+ return options.InternalAddPolicy(policyName, context =>
+ {
+ return RateLimitPartition.CreateTokenBucketLimiter((DefaultKeyType)new DefaultKeyType<PolicyNameKey>(new PolicyNameKey() { PolicyName = policyName }),
+ _ => tokenBucketRateLimiterOptions);
+ });
+ }
+
+ /// <summary>
+ /// Adds a new <see cref="FixedWindowRateLimiter"/> with the given <see cref="FixedWindowRateLimiterOptions"/> to the <see cref="RateLimiterOptions"/>.
+ /// </summary>
+ /// <param name="options">The <see cref="RateLimiterOptions"/> to add a limiter to.</param>
+ /// <param name="policyName">The name that will be associated with the limiter.</param>
+ /// <param name="fixedWindowRateLimiterOptions">The <see cref="FixedWindowRateLimiterOptions"/> to be used for the limiter.</param>
+ /// <returns>This <see cref="RateLimiterOptions"/>.</returns>
+ public static RateLimiterOptions AddFixedWindowLimiter(this RateLimiterOptions options, string policyName, FixedWindowRateLimiterOptions fixedWindowRateLimiterOptions)
+ {
+ return options.InternalAddPolicy(policyName, context =>
+ {
+ return RateLimitPartition.CreateFixedWindowLimiter((DefaultKeyType)new DefaultKeyType<PolicyNameKey>(new PolicyNameKey() { PolicyName = policyName }),
+ _ => fixedWindowRateLimiterOptions);
+ });
+ }
+
+ /// <summary>
+ /// Adds a new <see cref="SlidingWindowRateLimiter"/> with the given <see cref="SlidingWindowRateLimiterOptions"/> to the <see cref="RateLimiterOptions"/>.
+ /// </summary>
+ /// <param name="options">The <see cref="RateLimiterOptions"/> to add a limiter to.</param>
+ /// <param name="policyName">The name that will be associated with the limiter.</param>
+ /// <param name="slidingWindowRateLimiterOptions">The <see cref="SlidingWindowRateLimiterOptions"/> to be used for the limiter.</param>
+ /// <returns>This <see cref="RateLimiterOptions"/>.</returns>
+ public static RateLimiterOptions AddSlidingWindowLimiter(this RateLimiterOptions options, string policyName, SlidingWindowRateLimiterOptions slidingWindowRateLimiterOptions)
+ {
+ return options.InternalAddPolicy(policyName, context =>
+ {
+ return RateLimitPartition.CreateSlidingWindowLimiter((DefaultKeyType)new DefaultKeyType<PolicyNameKey>(new PolicyNameKey() { PolicyName = policyName }),
+ _ => slidingWindowRateLimiterOptions);
+ });
+ }
+
+ /// <summary>
+ /// Adds a new <see cref="ConcurrencyLimiter"/> with the given <see cref="ConcurrencyLimiterOptions"/> to the <see cref="RateLimiterOptions"/>.
+ /// </summary>
+ /// <param name="options">The <see cref="RateLimiterOptions"/> to add a limiter to.</param>
+ /// <param name="policyName">The name that will be associated with the limiter.</param>
+ /// <param name="concurrencyLimiterOptions">The <see cref="ConcurrencyLimiterOptions"/> to be used for the limiter.</param>
+ /// <returns>This <see cref="RateLimiterOptions"/>.</returns>
+ public static RateLimiterOptions AddConcurrencyLimiter(this RateLimiterOptions options, string policyName, ConcurrencyLimiterOptions concurrencyLimiterOptions)
+ {
+ return options.InternalAddPolicy(policyName, context =>
+ {
+ return RateLimitPartition.CreateConcurrencyLimiter((DefaultKeyType)new DefaultKeyType<PolicyNameKey>(new PolicyNameKey() { PolicyName = policyName }),
+ _ => concurrencyLimiterOptions);
+ });
+ }
+
+ /// <summary>
+ /// Adds a new no-op <see cref="RateLimiter"/> to the <see cref="RateLimiterOptions"/>.
+ /// </summary>
+ /// <param name="options">The <see cref="RateLimiterOptions"/> to add a limiter to.</param>
+ /// <param name="policyName">The name that will be associated with the limiter.</param>
+ /// <returns>This <see cref="RateLimiterOptions"/>.</returns>
+ public static RateLimiterOptions AddNoLimiter(this RateLimiterOptions options, string policyName)
+ {
+ return options.InternalAddPolicy(policyName, context =>
+ {
+ return RateLimitPartition.CreateNoLimiter((DefaultKeyType)new DefaultKeyType<PolicyNameKey>(new PolicyNameKey() { PolicyName = policyName }));
+ });
+ }
+}
diff --git a/src/Middleware/RateLimiting/src/RateLimitingMiddleware.cs b/src/Middleware/RateLimiting/src/RateLimitingMiddleware.cs
index a97aa7c9ee..e4a170e0f2 100644
--- a/src/Middleware/RateLimiting/src/RateLimitingMiddleware.cs
+++ b/src/Middleware/RateLimiting/src/RateLimitingMiddleware.cs
@@ -14,10 +14,14 @@ namespace Microsoft.AspNetCore.RateLimiting;
internal sealed partial class RateLimitingMiddleware
{
private readonly RequestDelegate _next;
- private readonly Func<HttpContext, RateLimitLease, Task> _onRejected;
+ private readonly Func<OnRejectedContext, CancellationToken, ValueTask>? _defaultOnRejected;
private readonly ILogger _logger;
- private readonly PartitionedRateLimiter<HttpContext> _limiter;
+ private readonly PartitionedRateLimiter<HttpContext>? _globalLimiter;
+ private readonly PartitionedRateLimiter<HttpContext> _endpointLimiter;
private readonly int _rejectionStatusCode;
+ private readonly IDictionary<string, DefaultRateLimiterPolicy> _policyMap;
+ private readonly DefaultKeyType _defaultPolicyKey = new DefaultKeyType<PolicyNameKey>(new PolicyNameKey { PolicyName = "__defaultPolicyKey" });
+ private readonly IServiceProvider _serviceProvider;
/// <summary>
/// Creates a new <see cref="RateLimitingMiddleware"/>.
@@ -25,15 +29,29 @@ internal sealed partial class RateLimitingMiddleware
/// <param name="next">The <see cref="RequestDelegate"/> representing the next middleware in the pipeline.</param>
/// <param name="logger">The <see cref="ILogger"/> used for logging.</param>
/// <param name="options">The options for the middleware.</param>
- public RateLimitingMiddleware(RequestDelegate next, ILogger<RateLimitingMiddleware> logger, IOptions<RateLimiterOptions> options)
+ /// <param name="serviceProvider">The service provider.</param>
+ public RateLimitingMiddleware(RequestDelegate next, ILogger<RateLimitingMiddleware> logger, IOptions<RateLimiterOptions> options, IServiceProvider serviceProvider)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
- _limiter = options.Value.Limiter;
- _onRejected = options.Value.OnRejected;
- _rejectionStatusCode = options.Value.DefaultRejectionStatusCode;
+ _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
+
+ _defaultOnRejected = options.Value.OnRejected;
+ _rejectionStatusCode = options.Value.RejectionStatusCode;
+ _policyMap = options.Value.PolicyMap;
+
+ // Use reflection to activate policies passed to AddPolicy<TPartitionKey, TPolicy>
+
+ foreach (var unactivatedPolicy in options.Value.UnactivatedPolicyMap)
+ {
+ _policyMap.Add(unactivatedPolicy.Key, unactivatedPolicy.Value(_serviceProvider));
+ }
+
+ _globalLimiter = options.Value.GlobalLimiter;
+ _endpointLimiter = CreateEndpointLimiter();
+
}
// TODO - EventSource?
@@ -44,30 +62,126 @@ internal sealed partial class RateLimitingMiddleware
/// <returns>A <see cref="Task"/> that completes when the request leaves.</returns>
public async Task Invoke(HttpContext context)
{
- using var lease = await TryAcquireAsync(context);
- if (lease.IsAcquired)
+ using var leaseContext = await TryAcquireAsync(context);
+ if (leaseContext.Lease.IsAcquired)
{
await _next(context);
}
else
{
+ var thisRequestOnRejected = _defaultOnRejected;
RateLimiterLog.RequestRejectedLimitsExceeded(_logger);
// OnRejected "wins" over DefaultRejectionStatusCode - we set DefaultRejectionStatusCode first,
// then call OnRejected in case it wants to do any further modification of the status code.
context.Response.StatusCode = _rejectionStatusCode;
- await _onRejected(context, lease);
+
+ // If this request was rejected by the endpoint limiter, use its OnRejected if available. Else
+ if (leaseContext.GlobalRejected == false)
+ {
+ DefaultRateLimiterPolicy? policy;
+ var policyName = context.GetEndpoint()?.Metadata.GetMetadata<IRateLimiterMetadata>()?.PolicyName;
+ // Use custom policy OnRejected if available, else use OnRejected from the Options if available.
+ if (policyName is not null && _policyMap.TryGetValue(policyName, out policy) && policy.OnRejected is not null)
+ {
+ thisRequestOnRejected = policy.OnRejected;
+ }
+ }
+ if (thisRequestOnRejected is not null)
+ {
+ await thisRequestOnRejected(new OnRejectedContext() { HttpContext = context, Lease = leaseContext.Lease }, context.RequestAborted);
+ }
}
}
- private ValueTask<RateLimitLease> TryAcquireAsync(HttpContext context)
+ private ValueTask<LeaseContext> TryAcquireAsync(HttpContext context)
{
- var lease = _limiter.Acquire(context);
- if (lease.IsAcquired)
+ var leaseContext = CombinedAcquire(context);
+ if (leaseContext.Lease.IsAcquired)
{
- return ValueTask.FromResult(lease);
+ return ValueTask.FromResult(leaseContext);
}
- return _limiter.WaitAsync(context, cancellationToken: context.RequestAborted);
+ return CombinedWaitAsync(context, context.RequestAborted);
+ }
+
+ private LeaseContext CombinedAcquire(HttpContext context)
+ {
+ RateLimitLease? globalLease = null;
+ RateLimitLease? endpointLease = null;
+
+ try
+ {
+ if (_globalLimiter is not null)
+ {
+ globalLease = _globalLimiter.Acquire(context);
+ if (!globalLease.IsAcquired)
+ {
+ return new LeaseContext() { GlobalRejected = true, Lease = globalLease };
+ }
+ }
+ endpointLease = _endpointLimiter.Acquire(context);
+ if (!endpointLease.IsAcquired)
+ {
+ globalLease?.Dispose();
+ return new LeaseContext() { GlobalRejected = false, Lease = endpointLease };
+ }
+ }
+ catch (Exception)
+ {
+ endpointLease?.Dispose();
+ globalLease?.Dispose();
+ throw;
+ }
+
+ return new LeaseContext() { Lease = new DefaultCombinedLease(globalLease, endpointLease)};
+ }
+
+ private async ValueTask<LeaseContext> CombinedWaitAsync(HttpContext context, CancellationToken cancellationToken)
+ {
+ RateLimitLease? globalLease = null;
+ RateLimitLease? endpointLease = null;
+
+ try
+ {
+ if (_globalLimiter is not null)
+ {
+ globalLease = await _globalLimiter.WaitAsync(context, cancellationToken: cancellationToken).ConfigureAwait(false);
+ if (!globalLease.IsAcquired)
+ {
+ return new LeaseContext() { GlobalRejected = true, Lease = globalLease };
+ }
+ }
+ endpointLease = await _endpointLimiter.WaitAsync(context, cancellationToken: cancellationToken).ConfigureAwait(false);
+ if (!endpointLease.IsAcquired)
+ {
+ globalLease?.Dispose();
+ return new LeaseContext() { GlobalRejected = false, Lease = endpointLease };
+ }
+ }
+ catch (Exception)
+ {
+ endpointLease?.Dispose();
+ globalLease?.Dispose();
+ throw;
+ }
+
+ return new LeaseContext() { Lease = new DefaultCombinedLease(globalLease, endpointLease) };
+ }
+
+ // Create the endpoint-specific PartitionedRateLimiter
+ private PartitionedRateLimiter<HttpContext> CreateEndpointLimiter()
+ {
+ // If we have a policy for this endpoint, use its partitioner. Else use a NoLimiter.
+ return PartitionedRateLimiter.Create<HttpContext, DefaultKeyType>(context =>
+ {
+ DefaultRateLimiterPolicy? policy;
+ var name = context.GetEndpoint()?.Metadata.GetMetadata<IRateLimiterMetadata>()?.PolicyName;
+ if (name is not null && _policyMap.TryGetValue(name, out policy))
+ {
+ return policy.GetPartition(context);
+ }
+ return RateLimitPartition.CreateNoLimiter<DefaultKeyType>(_defaultPolicyKey);
+ }, new DefaultKeyTypeEqualityComparer());
}
private static partial class RateLimiterLog
diff --git a/src/Middleware/RateLimiting/test/RateLimitingApplicationBuilderExtensionsTests.cs b/src/Middleware/RateLimiting/test/RateLimitingApplicationBuilderExtensionsTests.cs
index 37d6d5bc4c..45afd2182a 100644
--- a/src/Middleware/RateLimiting/test/RateLimitingApplicationBuilderExtensionsTests.cs
+++ b/src/Middleware/RateLimiting/test/RateLimitingApplicationBuilderExtensionsTests.cs
@@ -14,7 +14,7 @@ public class RateLimitingApplicationBuilderExtensionsTests : LoggedTest
[Fact]
public void UseRateLimiter_ThrowsOnNullAppBuilder()
{
- Assert.Throws<ArgumentNullException>(() => RateLimitingApplicationBuilderExtensions.UseRateLimiter(null));
+ Assert.Throws<ArgumentNullException>(() => RateLimiterApplicationBuilderExtensions.UseRateLimiter(null));
}
[Fact]
@@ -29,15 +29,15 @@ public class RateLimitingApplicationBuilderExtensionsTests : LoggedTest
{
// These are the options that should get used
var options = new RateLimiterOptions();
- options.DefaultRejectionStatusCode = 429;
- options.Limiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
+ options.RejectionStatusCode = 429;
+ options.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
// These should not get used
var services = new ServiceCollection();
services.Configure<RateLimiterOptions>(options =>
{
- options.Limiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
- options.DefaultRejectionStatusCode = 404;
+ options.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
+ options.RejectionStatusCode = 404;
});
services.AddLogging();
var serviceProvider = services.BuildServiceProvider();
diff --git a/src/Middleware/RateLimiting/test/RateLimitingMiddlewareTests.cs b/src/Middleware/RateLimiting/test/RateLimitingMiddlewareTests.cs
index 903b225ed4..f14d0fa0ab 100644
--- a/src/Middleware/RateLimiting/test/RateLimitingMiddlewareTests.cs
+++ b/src/Middleware/RateLimiting/test/RateLimitingMiddlewareTests.cs
@@ -1,11 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Threading.RateLimiting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
+using Moq;
namespace Microsoft.AspNetCore.RateLimiting;
@@ -15,19 +17,29 @@ public class RateLimitingMiddlewareTests : LoggedTest
public void Ctor_ThrowsExceptionsWhenNullArgs()
{
var options = CreateOptionsAccessor();
- options.Value.Limiter = new TestPartitionedRateLimiter<HttpContext>();
+ options.Value.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>();
Assert.Throws<ArgumentNullException>(() => new RateLimitingMiddleware(
null,
new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
- options));
+ options,
+ Mock.Of<IServiceProvider>()));
Assert.Throws<ArgumentNullException>(() => new RateLimitingMiddleware(c =>
- {
- return Task.CompletedTask;
- },
- null,
- options));
+ {
+ return Task.CompletedTask;
+ },
+ null,
+ options,
+ Mock.Of<IServiceProvider>()));
+
+ Assert.Throws<ArgumentNullException>(() => new RateLimitingMiddleware(c =>
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ null));
}
[Fact]
@@ -35,14 +47,15 @@ public class RateLimitingMiddlewareTests : LoggedTest
{
var flag = false;
var options = CreateOptionsAccessor();
- options.Value.Limiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(true));
+ options.Value.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(true));
var middleware = new RateLimitingMiddleware(c =>
- {
- flag = true;
- return Task.CompletedTask;
- },
- new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
- options);
+ {
+ flag = true;
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
await middleware.Invoke(new DefaultHttpContext());
Assert.True(flag);
@@ -53,19 +66,20 @@ public class RateLimitingMiddlewareTests : LoggedTest
{
var onRejectedInvoked = false;
var options = CreateOptionsAccessor();
- options.Value.Limiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
- options.Value.OnRejected = (httpContext, lease) =>
+ options.Value.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
+ options.Value.OnRejected = (context, token) =>
{
onRejectedInvoked = true;
- return Task.CompletedTask;
+ return ValueTask.CompletedTask;
};
var middleware = new RateLimitingMiddleware(c =>
- {
- return Task.CompletedTask;
- },
- new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
- options);
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
var context = new DefaultHttpContext();
await middleware.Invoke(context).DefaultTimeout();
@@ -78,20 +92,21 @@ public class RateLimitingMiddlewareTests : LoggedTest
{
var onRejectedInvoked = false;
var options = CreateOptionsAccessor();
- options.Value.Limiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
- options.Value.OnRejected = (httpContext, lease) =>
+ options.Value.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
+ options.Value.OnRejected = (context, token) =>
{
onRejectedInvoked = true;
- httpContext.Response.StatusCode = 429;
- return Task.CompletedTask;
+ context.HttpContext.Response.StatusCode = 429;
+ return ValueTask.CompletedTask;
};
var middleware = new RateLimitingMiddleware(c =>
- {
- return Task.CompletedTask;
- },
- new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
- options);
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
var context = new DefaultHttpContext();
await middleware.Invoke(context).DefaultTimeout();
@@ -103,18 +118,260 @@ public class RateLimitingMiddlewareTests : LoggedTest
public async Task RequestAborted_ThrowsTaskCanceledException()
{
var options = CreateOptionsAccessor();
- options.Value.Limiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
+ options.Value.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
+
+ var middleware = new RateLimitingMiddleware(c =>
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
+
+ var context = new DefaultHttpContext();
+ context.RequestAborted = new CancellationToken(true);
+ await Assert.ThrowsAsync<TaskCanceledException>(() => middleware.Invoke(context)).DefaultTimeout();
+ }
+
+ [Fact]
+ public async Task EndpointLimiter_Rejects()
+ {
+ var onRejectedInvoked = false;
+ var options = CreateOptionsAccessor();
+ var name = "myEndpoint";
+ options.Value.AddPolicy<string>(name, (context =>
+ {
+ return RateLimitPartition.Create<string>("myLimiter", (key =>
+ {
+ return new TestRateLimiter(false);
+ }));
+ }));
+ options.Value.OnRejected = (context, token) =>
+ {
+ onRejectedInvoked = true;
+ context.HttpContext.Response.StatusCode = 429;
+ return ValueTask.CompletedTask;
+ };
+
+ var middleware = new RateLimitingMiddleware(c =>
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
+
+ var context = new DefaultHttpContext();
+ context.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new RateLimiterMetadata(name)), "Test endpoint"));
+ await middleware.Invoke(context).DefaultTimeout();
+ Assert.True(onRejectedInvoked);
+ Assert.Equal(StatusCodes.Status429TooManyRequests, context.Response.StatusCode);
+ }
+
+ [Fact]
+ public async Task EndpointLimiterConvenienceMethod_Rejects()
+ {
+ var onRejectedInvoked = false;
+ var options = CreateOptionsAccessor();
+ var name = "myEndpoint";
+ options.Value.AddFixedWindowLimiter(name, new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0, TimeSpan.Zero, autoReplenishment: false));
+ options.Value.OnRejected = (context, token) =>
+ {
+ onRejectedInvoked = true;
+ context.HttpContext.Response.StatusCode = 429;
+ return ValueTask.CompletedTask;
+ };
+
+ var middleware = new RateLimitingMiddleware(c =>
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
+
+ var context = new DefaultHttpContext();
+ context.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new RateLimiterMetadata(name)), "Test endpoint"));
+ await middleware.Invoke(context).DefaultTimeout();
+ Assert.False(onRejectedInvoked);
+ await middleware.Invoke(context).DefaultTimeout();
+ Assert.True(onRejectedInvoked);
+ Assert.Equal(StatusCodes.Status429TooManyRequests, context.Response.StatusCode);
+ }
+
+ [Fact]
+ public async Task EndpointLimiterRejects_EndpointOnRejectedFires()
+ {
+ var globalOnRejectedInvoked = false;
+ var options = CreateOptionsAccessor();
+ var name = "myEndpoint";
+ // This is the policy that should get used
+ options.Value.AddPolicy<string>(name, new TestRateLimiterPolicy("myKey", 404, false));
+ // This OnRejected should be ignored in favor of the one on the policy
+ options.Value.OnRejected = (context, token) =>
+ {
+ globalOnRejectedInvoked = true;
+ context.HttpContext.Response.StatusCode = 429;
+ return ValueTask.CompletedTask;
+ };
+
+ var middleware = new RateLimitingMiddleware(c =>
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
+
+ var context = new DefaultHttpContext();
+ context.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new RateLimiterMetadata(name)), "Test endpoint"));
+ await middleware.Invoke(context).DefaultTimeout();
+ Assert.False(globalOnRejectedInvoked);
+
+ Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode);
+ }
+
+ [Fact]
+ public async Task GlobalAndEndpoint_GlobalRejects_GlobalWins()
+ {
+ var globalOnRejectedInvoked = false;
+ var options = CreateOptionsAccessor();
+ var name = "myEndpoint";
+ // Endpoint always allows - it should not fire
+ options.Value.AddPolicy<string>(name, new TestRateLimiterPolicy("myKey", 404, true));
+ // Global never allows - it should fire
+ options.Value.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
+ options.Value.OnRejected = (context, token) =>
+ {
+ globalOnRejectedInvoked = true;
+ context.HttpContext.Response.StatusCode = 429;
+ return ValueTask.CompletedTask;
+ };
+
+ var middleware = new RateLimitingMiddleware(c =>
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
+
+ var context = new DefaultHttpContext();
+ context.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new RateLimiterMetadata(name)), "Test endpoint"));
+ await middleware.Invoke(context).DefaultTimeout();
+ Assert.True(globalOnRejectedInvoked);
+
+ Assert.Equal(StatusCodes.Status429TooManyRequests, context.Response.StatusCode);
+ }
+
+ [Fact]
+ public async Task GlobalAndEndpoint_EndpointRejects_EndpointWins()
+ {
+ var globalOnRejectedInvoked = false;
+ var options = CreateOptionsAccessor();
+ var name = "myEndpoint";
+ // Endpoint never allows - it should fire
+ options.Value.AddPolicy<string>(name, new TestRateLimiterPolicy("myKey", 404, false));
+ // Global always allows - it should not fire
+ options.Value.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(true));
+ options.Value.OnRejected = (context, token) =>
+ {
+ globalOnRejectedInvoked = true;
+ context.HttpContext.Response.StatusCode = 429;
+ return ValueTask.CompletedTask;
+ };
+
+ var middleware = new RateLimitingMiddleware(c =>
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
+
+ var context = new DefaultHttpContext();
+ context.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new RateLimiterMetadata(name)), "Test endpoint"));
+ await middleware.Invoke(context).DefaultTimeout();
+ Assert.False(globalOnRejectedInvoked);
+
+ Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode);
+ }
+
+ [Fact]
+ public async Task GlobalAndEndpoint_BothReject_GlobalWins()
+ {
+ var globalOnRejectedInvoked = false;
+ var options = CreateOptionsAccessor();
+ var name = "myEndpoint";
+ // Endpoint never allows - it should not fire
+ options.Value.AddPolicy<string>(name, new TestRateLimiterPolicy("myKey", 404, false));
+ // Global never allows - it should fire
+ options.Value.GlobalLimiter = new TestPartitionedRateLimiter<HttpContext>(new TestRateLimiter(false));
+ options.Value.OnRejected = (context, token) =>
+ {
+ globalOnRejectedInvoked = true;
+ context.HttpContext.Response.StatusCode = 429;
+ return ValueTask.CompletedTask;
+ };
+
+ var middleware = new RateLimitingMiddleware(c =>
+ {
+ return Task.CompletedTask;
+ },
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ Mock.Of<IServiceProvider>());
+
+ var context = new DefaultHttpContext();
+ context.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new RateLimiterMetadata(name)), "Test endpoint"));
+ await middleware.Invoke(context).DefaultTimeout();
+ Assert.True(globalOnRejectedInvoked);
+
+ Assert.Equal(StatusCodes.Status429TooManyRequests, context.Response.StatusCode);
+ }
+
+ [Fact]
+ public async Task EndpointLimiterRejects_EndpointOnRejectedFires_WithIRateLimiterPolicy()
+ {
+ var globalOnRejectedInvoked = false;
+ var options = CreateOptionsAccessor();
+ var name = "myEndpoint";
+ // This is the policy that should get used
+ options.Value.AddPolicy<string, TestRateLimiterPolicy>(name);
+ // This OnRejected should be ignored in favor of the one on the policy
+ options.Value.OnRejected = (context, token) =>
+ {
+ globalOnRejectedInvoked = true;
+ context.HttpContext.Response.StatusCode = 429;
+ return ValueTask.CompletedTask;
+ };
+
+ // Configure the service provider with the args to the TestRateLimiterPolicy ctor
+ var mockServiceProvider = new Mock<IServiceProvider>();
+ mockServiceProvider
+ .Setup(sp => sp.GetService(typeof(string)))
+ .Returns("myKey");
+ mockServiceProvider
+ .Setup(sp => sp.GetService(typeof(int)))
+ .Returns(404);
+ mockServiceProvider
+ .Setup(sp => sp.GetService(typeof(bool)))
+ .Returns(false);
var middleware = new RateLimitingMiddleware(c =>
{
return Task.CompletedTask;
},
- new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
- options);
+ new NullLoggerFactory().CreateLogger<RateLimitingMiddleware>(),
+ options,
+ mockServiceProvider.Object);
var context = new DefaultHttpContext();
- context.RequestAborted = new CancellationToken(true);
- await Assert.ThrowsAsync<TaskCanceledException>(() => middleware.Invoke(context)).DefaultTimeout();
+ context.SetEndpoint(new Endpoint(c => Task.CompletedTask, new EndpointMetadataCollection(new RateLimiterMetadata(name)), "Test endpoint"));
+ await middleware.Invoke(context).DefaultTimeout();
+ Assert.False(globalOnRejectedInvoked);
+
+ Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode);
}
private IOptions<RateLimiterOptions> CreateOptionsAccessor() => Options.Create(new RateLimiterOptions());
diff --git a/src/Middleware/RateLimiting/test/RateLimitingOptionsTests.cs b/src/Middleware/RateLimiting/test/RateLimitingOptionsTests.cs
index 839a9d2da0..a58512e28f 100644
--- a/src/Middleware/RateLimiting/test/RateLimitingOptionsTests.cs
+++ b/src/Middleware/RateLimiting/test/RateLimitingOptionsTests.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Threading.RateLimiting;
+using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.RateLimiting;
@@ -8,16 +10,39 @@ namespace Microsoft.AspNetCore.RateLimiting;
public class RateLimitingOptionsTests
{
[Fact]
- public void ThrowsOnNullLimiter()
+ public void AddPolicy_ThrowsOnNullPolicyName()
{
var options = new RateLimiterOptions();
- Assert.Throws<ArgumentNullException>(() => options.Limiter = null);
+ Assert.Throws<ArgumentNullException>(() => options.AddPolicy<string>(null, context => RateLimitPartition.CreateNoLimiter<string>("myKey")));
}
[Fact]
- public void ThrowsOnNullOnRejected()
+ public void AddPolicy_ThrowsOnNullPartitioner()
{
var options = new RateLimiterOptions();
- Assert.Throws<ArgumentNullException>(() => options.OnRejected = null);
+ Assert.Throws<ArgumentNullException>(() => options.AddPolicy<string>("myKey", partitioner: null));
+ }
+
+ [Fact]
+ public void AddPolicy_ThrowsOnNullPolicy()
+ {
+ var options = new RateLimiterOptions();
+ Assert.Throws<ArgumentNullException>(() => options.AddPolicy<string>("myKey", policy: null));
+ }
+
+ [Fact]
+ public void AddPolicy_ThrowsOnDuplicateName()
+ {
+ var options = new RateLimiterOptions();
+ options.AddPolicy<string>("myKey", context => RateLimitPartition.CreateNoLimiter<string>("myKey"));
+ Assert.Throws<ArgumentException>(() => options.AddPolicy<string>("myKey", context => RateLimitPartition.CreateNoLimiter<string>("yourKey")));
+ }
+
+ [Fact]
+ public void AddPolicy_Generic_ThrowsOnDuplicateName()
+ {
+ var options = new RateLimiterOptions();
+ options.AddPolicy<string>("myKey", context => RateLimitPartition.CreateNoLimiter<string>("myKey"));
+ Assert.Throws<ArgumentException>(() => options.AddPolicy<string, TestRateLimiterPolicy>("myKey"));
}
}
diff --git a/src/Middleware/RateLimiting/test/TestRateLimiterPolicy.cs b/src/Middleware/RateLimiting/test/TestRateLimiterPolicy.cs
new file mode 100644
index 0000000000..777935a092
--- /dev/null
+++ b/src/Middleware/RateLimiting/test/TestRateLimiterPolicy.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Threading.RateLimiting;
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.RateLimiting;
+internal class TestRateLimiterPolicy : IRateLimiterPolicy<string>
+{
+ private readonly string _key;
+ private readonly bool _alwaysAccept;
+ private readonly Func<OnRejectedContext, CancellationToken, ValueTask> _onRejected;
+
+ public TestRateLimiterPolicy(string key, int statusCode, bool alwaysAccept)
+ {
+ _key = key;
+ _alwaysAccept = alwaysAccept;
+
+ _onRejected = (context, token) =>
+ {
+ context.HttpContext.Response.StatusCode = statusCode;
+ return ValueTask.CompletedTask;
+ };
+ }
+
+ public Func<OnRejectedContext, CancellationToken, ValueTask> OnRejected { get => _onRejected; }
+
+ public RateLimitPartition<string> GetPartition(HttpContext httpContext)
+ {
+ return RateLimitPartition.Create<string>(_key, (key =>
+ {
+ return new TestRateLimiter(_alwaysAccept);
+ }));
+ }
+}