platform/lib/src/rate_limiter.dart

50 lines
2 KiB
Dart
Raw Normal View History

2019-08-14 18:49:14 +00:00
import 'dart:async';
2019-08-14 18:46:53 +00:00
import 'package:angel_framework/angel_framework.dart';
2019-08-14 19:09:48 +00:00
import 'package:angel_security/angel_security.dart';
import 'rate_limiting_window.dart';
2019-08-14 18:46:53 +00:00
/// A base class that facilitates rate limiting API's or endpoints,
/// typically to prevent spam and abuse.
2019-08-14 18:49:14 +00:00
///
/// The rate limiter operates under the assumption that a [User] object
/// can be computed from each request, as well as information about
/// the current rate-limiting window.
abstract class RateLimiter<User> {
2019-08-14 19:17:02 +00:00
/// The maximum number of points that may be consumed
/// within the given [windowDuration].
final int maxPointsPerWindow;
2019-08-14 18:46:53 +00:00
2019-08-14 19:17:02 +00:00
/// The amount of time, during which, a user is not allowed to consume
/// more than [maxPointsPerWindow].
final Duration windowDuration;
2019-08-14 18:46:53 +00:00
2019-08-14 19:17:02 +00:00
RateLimiter(this.maxPointsPerWindow, this.windowDuration);
2019-08-14 19:09:48 +00:00
/// Computes the current window in which the user is acting.
2019-08-14 19:17:02 +00:00
///
2019-08-14 19:09:48 +00:00
/// For example, if your API was limited to 1000 requests/hour,
/// then you would return a window containing the current hour,
/// and the number of requests the user has sent in the past hour.
FutureOr<RateLimitingWindow<User>> getCurrentWindow(
RequestContext req, ResponseContext res);
2019-08-14 19:17:02 +00:00
/// Updates the underlying store with information about the new
/// [window] that the user is operating in.
2019-08-14 19:19:37 +00:00
FutureOr<void> updateCurrentWindow(
RequestContext req, ResponseContext res, RateLimitingWindow<User> window);
/// Computes the amount of points that a given request will cost. This amount
/// is then added to the amount of points that the user has already consumed
/// in the current [window].
///
/// The default behavior is to return `1`, which signifies that all requests
/// carry the same weight.
FutureOr<int> getEndpointCost(RequestContext req, ResponseContext res,
RateLimitingWindow<User> window) {
return Future<int>.value(1);
}
2019-08-14 19:09:48 +00:00
2019-08-14 19:17:02 +00:00
FutureOr<Object> denyRequest(RequestContext req, ResponseContext res,
RateLimitingWindow<User> window) {}
2019-08-14 18:46:53 +00:00
}