Closed
Description
NOTE - This is the original draft of the proposal. The updated proposal is at this comment: #42667 (comment)
namespace Microsoft.AspNetCore.RateLimiting
+ public interface IRateLimiterMetadata
+ {
+ }
+ public interface IRequireRateLimiterMetadata : IRateLimiterMetadata
+ {
+ string PolicyName { get; }
+ }
+ public class RequireRateLimiterMetadata : IRequireRateLimiterMetadata
+ {
+ public RequireRateLimiterMetadata (string policyName)
+ public string PolicyName { get; }
+ }
+ public interface IDisableRateLimiterMetadata : IRateLimiterMetadata
+ {
+ }
+ public class DisableRateLimiterMetadata : IDisableRateLimiterMetadata
+ {
+ public RequireRateLimiterMetadata ()
+ }
public interface IRateLimiterPolicy<TPartitionKey>
{
- Func<OnRejectedContext, CancellationToken, ValueTask>? OnRejected { get; }
+ ValueTask OnRejected(OnRejectedContext onRejectedContext, CancellationToken cancellationToken)
}
namespace Microsoft.AspNetCore.Builder
public static class RateLimiterApplicationBuilderExtensions
{
public static IApplicationBuilder UseRateLimiter(this IApplicationBuilder app)
- public static IApplicationBuilder UseRateLimiter(this IApplicationBuilder app, RateLimiterOptions options)
}
+ public static class RateLimiterServiceCollectionExtensions
+ {
+ public static IServiceCollection AddRateLimiter(this IServiceCollection services, Action<RateLimiterOptions > configureOptions)
+ }
public static class RateLimiterOptionsExtensions
{
- public static RateLimiterOptions AddNoLimiter(this RateLimiterOptions options, string policyName)
}
public static class RateLimiterEndpointConventionBuilderExtensions
{
+ public static TBuilder DisableRateLimiting<TBuilder>(this TBuilder builder) where TBuilder : IEndpointConventionBuilder
}
Q's - keep OnRejected
as a Func
because it's nullable? Change extension methods like AddTokenBucketLimiter
to AddTokenBucketLimiterPolicy
? Add an attribute for MVC Controllers?
Activity
BrennanConroy commentedon Jul 11, 2022
I like the idea of skipping the middleware suggested in #41667 (comment)
ghost commentedon Jul 11, 2022
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
halter73 commentedon Jul 14, 2022
Meeting notes:
Let's get rid of the
IRateLimiterMetadata
inheritance hiearcy.IRequireRateLimiterMetadata
toIRateLimiterMetadata
. AndRequireRateLimiterMetadata
toRateLimiterMetadata
.IDisableRateLimiterMetadata
stays the same name.Should we allow policies defined inline?
UseRateLimiter(this IApplicationBuilder app, RateLimiterOptions options)
should stay. We should still addAddRateLimiter
. This is the same pattern asAddWebSockets
.Let's keep
Func<OnRejectedContext, CancellationToken, ValueTask>? OnRejected { get; }
so we know whether or not to call the globalOnRejected
callback. If we make it a normal method instead, we'd have to be okay with okay with always running the globalOnRejected
first.Let's add attributes!
[RateLimit("MyPolicy")]
?Let's put everything in the ASP.NET Core shared framework. We'll have to include
System.Threading.RateLimiting
in the ASP.NET Core shared framework similar toSystem.IO.Pipelines
.One last curveball from @DamianEdwards: Why can't I configure the rate limiter options (e.g.
TokenBucketRateLimiterOptions
) with a callback like every other "option" type?AddTokenBucketLimiter
to take anAction<TokenBucketRateLimiterOptions>
instead ofTokenBucketRateLimiterOptions
directly.davidfowl commentedon Jul 15, 2022
This looks great so far 😄
Kahbazi commentedon Jul 15, 2022
How about this one:
This is according to the Guidelines and can be overriden if necessary.
Also
[DisableRateLimit]
?Can it be
Action<TokenBucketRateLimiterOptions, HttpContext>
? This way the options could be based on the custom metadata on an endpoint.davidfowl commentedon Jul 15, 2022
Agree with @Kahbazi on the disable attribute. We need attributes for anything we have methods for.
DamianEdwards commentedon Jul 15, 2022
Why does the
IDisableRateLimiterMetadata
need a property at all? Shouldn't it simply be a marker, likeIAllowAnonymous
?18 remaining items
wtgodbe commentedon Aug 1, 2022
We think that this isn't a broad enough use case to merit its addition at the moment, though we could be open to it in the future. It would also add complexity in the way we instantiate RateLimiters/Policies, since for the ones added in this way, we'd have to wait until we were in the middleware to do so.
wtgodbe commentedon Aug 9, 2022
I'm proposing a slight change to the approved API.
By putting an EnableRateLimitingAttribute on the endpoint with a null PolicyName, and setting an internal DefaultRateLimiterPolicy field on that EnableRateLimitingAttribute. PolicyName will only ever be null when we go through this code path – we’ll still throw if the user tries to set the PolicyName as null.
Another option which I just thought of would be to not make PolicyName nullable & have RequireRateLimiting<TBuilder, TPartitionKey> set a new EnableRateLimitingAttribute with some arbitrary PolicyName like the empty string – the presence of a
DefaultRateLimiterPolicy
on theEnableRateLimitingAttribute
should be sufficient to tell the middleware that the attribute came thru this code path, and to just ignore the PolicyName.ghost commentedon Aug 9, 2022
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
halter73 commentedon Aug 9, 2022
I think the nullability change makes sense here. Someone could easily name their policy
"DefaultRateLimiterPolicy"
, and now there might be some confusion about what policy that actually means. We could just a more obscure name and prevent anyone from adding a conflicting policy name, but I prefer making it clear that a policy can be unnamed.I think we should approve this API.
halter73 commentedon Aug 10, 2022
API review Notes:
API Approved! (Diff from previously approved API)