Documentation
¶
Overview ¶
Package singleflight provides request-coalescing middleware for celeris.
When several identical requests arrive concurrently, only the first (the "leader") executes the handler chain; the rest (the "waiters") block until the leader finishes and then receive a copy of its response. This absorbs thundering-herd bursts on hot endpoints so they hit the backend once.
Install it with New, optionally passing a Config. The zero-value configuration deduplicates on method + path + sorted query string + Authorization + Cookie, so requests from different authenticated users are never coalesced. Use Config.KeyFunc to change the key, and Config.Skip or Config.SkipPaths to exclude requests (for example non-idempotent methods or large-response endpoints). Waiter responses carry an "x-singleflight: HIT" header.
server.Use(singleflight.New())
Singleflight buffers the leader's response, so install it after timeout middleware and before response transforms such as compress or etag. It is intended for idempotent reads; a custom KeyFunc that returns user-specific data must incorporate user identity to avoid cross-user leakage.
Documentation ¶
Full guides and examples: https://goceleris.dev/docs/middleware-traffic
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func New ¶
func New(config ...Config) celeris.HandlerFunc
New creates a singleflight middleware with the given config.
Example ¶
package main
import (
"github.com/goceleris/celeris/middleware/singleflight"
)
func main() {
// Deduplicate concurrent identical GET requests using the default key
// (method + path + sorted query string).
// s := celeris.New()
// s.Use(singleflight.New())
_ = singleflight.New()
}
Output:
Example (CustomKey) ¶
package main
import (
"github.com/goceleris/celeris"
"github.com/goceleris/celeris/middleware/singleflight"
)
func main() {
// Use only the path as the deduplication key, ignoring query parameters.
_ = singleflight.New(singleflight.Config{
KeyFunc: func(c *celeris.Context) string {
return c.Method() + "\x00" + c.Path()
},
})
}
Output:
Example (SkipNonGET) ¶
package main
import (
"github.com/goceleris/celeris"
"github.com/goceleris/celeris/middleware/singleflight"
)
func main() {
// Only deduplicate GET and HEAD requests (recommended).
_ = singleflight.New(singleflight.Config{
Skip: func(c *celeris.Context) bool {
m := c.Method()
return m != "GET" && m != "HEAD"
},
})
}
Output:
Types ¶
type Config ¶
type Config struct {
// Skip defines a function to skip this middleware for certain requests.
Skip func(c *celeris.Context) bool
// SkipPaths lists paths to skip (exact match).
SkipPaths []string
// KeyFunc extracts the deduplication key from the request. Requests
// with the same key that arrive while a leader request is in-flight
// are coalesced — waiters receive a copy of the leader's response.
//
// Default: method + "\x00" + path + "\x00" + sorted-query-string
// + "\x00" + Authorization header + "\x00" + Cookie header. The
// Authorization and Cookie components ensure that requests from
// different authenticated users produce different keys, preventing
// cross-user data leakage. Unauthenticated requests (no auth/cookie
// headers) still coalesce normally.
//
// If you provide a custom KeyFunc, ensure it incorporates user
// identity for any endpoint that returns user-specific data.
KeyFunc func(c *celeris.Context) string
}
Config defines the singleflight middleware configuration.