mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-05 22:27:03 +02:00
57 lines
1.6 KiB
Go
57 lines
1.6 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package limits
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
)
|
|
|
|
//lint:ignore ST1005 Vault is the product name
|
|
var ErrCapacity = errors.New("Vault server temporarily overloaded")
|
|
|
|
const (
|
|
WriteLimiter = "write"
|
|
SpecialPathLimiter = "special-path"
|
|
)
|
|
|
|
// HTTPLimiter is a convenience struct that we use to wrap some logical request
|
|
// context and prevent dependence on Core.
|
|
type HTTPLimiter struct {
|
|
Method string
|
|
PathLimited bool
|
|
LookupFunc func(key string) *RequestLimiter
|
|
}
|
|
|
|
// CtxKeyDisableRequestLimiter holds the HTTP Listener's disable config if set.
|
|
type CtxKeyDisableRequestLimiter struct{}
|
|
|
|
func (c CtxKeyDisableRequestLimiter) String() string {
|
|
return "disable_request_limiter"
|
|
}
|
|
|
|
// Acquire checks the HTTPLimiter metadata to determine if an HTTP request
|
|
// should be limited, or simply passed through as a no-op.
|
|
func (h *HTTPLimiter) Acquire(ctx context.Context) (*RequestListener, bool) {
|
|
// If the limiter is disabled, return an empty wrapper so the limiter is a
|
|
// no-op and indicate that the request can proceed.
|
|
if disable := ctx.Value(CtxKeyDisableRequestLimiter{}); disable != nil && disable.(bool) {
|
|
return &RequestListener{}, true
|
|
}
|
|
|
|
lim := &RequestLimiter{}
|
|
if h.PathLimited {
|
|
lim = h.LookupFunc(SpecialPathLimiter)
|
|
} else {
|
|
switch h.Method {
|
|
case http.MethodGet, http.MethodHead, http.MethodTrace, http.MethodOptions:
|
|
// We're only interested in the inverse, so do nothing here.
|
|
default:
|
|
lim = h.LookupFunc(WriteLimiter)
|
|
}
|
|
}
|
|
return lim.Acquire(ctx)
|
|
}
|