Documentation
¶
Overview ¶
Package ratelimit bounds how often a caller may do something. It provides a declarative policy table, an in-memory sliding-window limiter, and the seams a deployment fills to add a challenge or a signup policy.
Index ¶
Constants ¶
const DefaultCapacity = 100_000
DefaultCapacity bounds how many keys the limiter tracks before it starts failing open.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Challenge ¶
type Challenge interface {
Provider() string
SiteKey() string
Verify(ctx context.Context, scope Scope, token string, clientIP string) error
}
Challenge verifies a proof-of-humanity token. Provider and SiteKey are exposed through the instance profile so the web app can render the matching widget. A nil Challenge means none is configured.
type Decision ¶
type Decision struct {
// Allowed is true when the request may proceed.
Allowed bool
// Rule is the rule that was consulted; zero when the scope is unlimited.
Rule Rule
// Remaining is how many units are left in the window before the call.
Remaining int
// RetryAfter is how long the caller should wait when refused.
RetryAfter time.Duration
}
Decision is the answer to an Allowed call.
type Limiter ¶
type Limiter interface {
Consume(scope Scope, key string, cost int) Decision
Refund(scope Scope, key string, cost int)
Allowed(scope Scope, key string, cost int) Decision
Hit(scope Scope, key string, cost int)
}
Limiter answers whether an activity may proceed and records that it did. Consume does both atomically and is what every-attempt-counts callers use. A caller that only counts some outcomes, such as a failed sign-in, still consumes up front so concurrent attempts cannot share one remaining unit, and calls Refund when the outcome turns out not to count. Allowed is a read and Hit a write for callers that need neither.
type MemoryLimiter ¶
type MemoryLimiter struct {
// contains filtered or unexported fields
}
MemoryLimiter is a sliding-window counter kept in process memory. Each key holds the count for the current fixed window and the previous one; the estimate weights the previous window by how much of it still overlaps the sliding window. Memory is constant per key.
func NewMemoryLimiter ¶
func NewMemoryLimiter(policy Policy, options ...MemoryOption) *MemoryLimiter
NewMemoryLimiter creates a limiter over the given policy.
func (*MemoryLimiter) Allowed ¶
func (l *MemoryLimiter) Allowed(scope Scope, key string, cost int) Decision
Allowed reports whether cost more units fit in the window for scope and key.
func (*MemoryLimiter) Consume ¶
func (l *MemoryLimiter) Consume(scope Scope, key string, cost int) Decision
Consume admits and records cost units in one step, so concurrent callers cannot all be admitted on the strength of the same remaining budget.
type MemoryOption ¶
type MemoryOption func(*MemoryLimiter)
MemoryOption tunes a MemoryLimiter.
func WithClock ¶
func WithClock(now func() time.Time) MemoryOption
WithClock replaces the time source, for tests.
type Policy ¶
Policy maps scopes to rules. A scope missing from the policy is unlimited.
func DefaultPolicy ¶
func DefaultPolicy() Policy
DefaultPolicy is the table shipped by the open-source binary. The numbers are starting points sized so that a household or small office behind one address is never throttled in ordinary use.
type Scope ¶
type Scope string
Scope names one counted activity. Scopes are the rows of the policy table.
const ( // ScopeAnonymous is the catch-all budget for requests without an identity, per client address. ScopeAnonymous Scope = "anonymous" // ScopeAuthenticated is the catch-all budget for requests with an identity, per user. ScopeAuthenticated Scope = "authenticated" // ScopeSignInIP counts failed sign-ins per client address. ScopeSignInIP Scope = "signin_ip" // ScopeSignInAccount counts failed password sign-ins per submitted username. ScopeSignInAccount Scope = "signin_account" // ScopeSignupIP counts self-service registrations per client address. ScopeSignupIP Scope = "signup_ip" // ScopeValidateIP counts validate-only registration probes per client address. ScopeValidateIP Scope = "validate_ip" // ScopePasswordResetIP is reserved for the password reset flow, per client address. ScopePasswordResetIP Scope = "password_reset_ip" // ScopePasswordResetEmail is reserved for the password reset flow, per canonical email. ScopePasswordResetEmail Scope = "password_reset_email" // ScopeLinkMetadata counts link preview fetches per URL requested. ScopeLinkMetadata Scope = "link_metadata" // ScopeUploadUser counts upload starts per user. ScopeUploadUser Scope = "upload_user" // ScopeTranscribeUser counts transcription calls per user. ScopeTranscribeUser Scope = "transcribe_user" // ScopeWriteUser counts content creation per user. ScopeWriteUser Scope = "write_user" // ScopeArchiveUser counts memo exports and imports per user. ScopeArchiveUser Scope = "archive_user" )
Scopes shipped by the open-source binary. See docs/design/api-abuse-controls.md.