Help us shape the future of Go! Take the 2026 Go Developer Survey

eprefusal

package
v1.149.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package eprefusal counts the requests an endpoint refused before its handler ran (#2208): at the bot check, a rate limit, the body limit, the caller's credential, or a cross-origin preflight from an origin the binding does not list. An answered request is audited; a refused one was not, so a flood refused at the bot check, which is what an administrator looks for on a public endpoint, showed nowhere.

A replica counts in memory and adds its counts to the database every few seconds, one row per endpoint, hour and reason: a flood moves a counter rather than writing a row per request, so counting refusals does not make refusing them cost more.

Index

Constants

View Source
const (
	ReasonBotCheck        = "bot_check"
	ReasonRateLimit       = "rate_limit"
	ReasonCallerRateLimit = "caller_rate_limit"
	ReasonBodyLimit       = "body_limit"
	ReasonCredential      = "credential"
	ReasonOrigin          = "origin"
)

The reasons a request is refused before its handler runs.

View Source
const DefaultFlush = 10 * time.Second

DefaultFlush is how often a replica adds its counts.

View Source
const Retention = 30 * 24 * time.Hour

Retention is how long the counts are kept.

Variables

This section is empty.

Functions

This section is empty.

Types

type Count

type Count struct {
	EndpointID string    `json:"-"`
	Hour       time.Time `json:"hour"`
	Reason     string    `json:"reason"`
	Count      int64     `json:"count"`
}

Count is how many requests to one endpoint were refused for one reason in one hour.

type Counter

type Counter struct {
	// contains filtered or unexported fields
}

Counter counts this replica's refusals in memory and adds them to the store on its loop.

func NewCounter

func NewCounter(store adder, flush time.Duration) *Counter

NewCounter counts into store, adding every flush (DefaultFlush when zero).

func (*Counter) Flush

func (c *Counter) Flush(ctx context.Context) error

Flush adds what has been counted since the last flush. A batch the store refuses is put back, to be added on the next flush.

func (*Counter) Refused

func (c *Counter) Refused(endpointID, reason string)

Refused counts one refused request. Nil-safe, and never blocks on the database.

func (*Counter) Start

func (c *Counter) Start(ctx context.Context) error

Start runs the flush loop, on a context ctx's ending does not stop: Stop does. A second call does nothing.

func (*Counter) Stop

func (c *Counter) Stop(ctx context.Context) error

Stop ends the loop and adds what is still counted, so a replica that stops loses no refusal it saw.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store keeps the counts.

func NewStore

func NewStore(db *sql.DB) *Store

NewStore is the store over db.

func (*Store) Add

func (s *Store) Add(ctx context.Context, counts []Count) error

Add adds counts to the hours and reasons they are for, in one statement.

func (*Store) Since

func (s *Store) Since(ctx context.Context, endpointID string, since time.Time) ([]Count, error)

Since reads every endpoint's counts from since on, by hour and reason. An empty endpointID reads every endpoint's.

func (*Store) Sweep

func (s *Store) Sweep(ctx context.Context, cutoff time.Time) (int64, error)

Sweep deletes the counts for hours before cutoff.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL