HTTP plugin: warn on uncached repeated GET requests (#31932)

This commit is contained in:
andig 2026-07-19 13:06:27 +02:00 • committed by GitHub
parent f56aae4aa0
commit 01b4c38231
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 57 additions and 0 deletions

View file

@ -27,6 +27,7 @@ type HTTP struct {
body string
pipeline *pipeline.Pipeline
mu *sync.Mutex
log *util.Logger
}
func init() {
@ -100,6 +101,7 @@ func NewHTTP(log *util.Logger, method, uri string, insecure bool, cache time.Dur
Helper: request.NewHelper(log),
url: uri,
method: method,
log: log,
}
// build the cache stack without logging so the logging tripper
@ -219,6 +221,11 @@ func (p *HTTP) request(url string, body string) ([]byte, error) {
return []byte{}, err
}
// warn on uncached GET polling: a configured cache would spare the roundtrip
if key := stripQuery(url); p.method == http.MethodGet && p.mu == nil && repeatedGet(key, time.Now()) {
p.log.WARN.Printf("uncached request repeated within 1s, please report at https://github.com/evcc-io/evcc/issues: %s", key)
}
val, err := p.DoBody(req)
if err != nil {
if err2 := knownErrors(val); err2 != nil {
@ -229,6 +236,37 @@ func (p *HTTP) request(url string, body string) ([]byte, error) {
return val, err
}
type httpAccess struct {
last time.Time
warned bool
}
var (
httpSeenMu sync.Mutex
httpSeen = make(map[string]httpAccess)
)
// stripQuery drops the query and fragment so cache-busting params do not make
// each poll look like a distinct url.
func stripQuery(url string) string {
if i := strings.IndexAny(url, "?#"); i >= 0 {
return url[:i]
}
return url
}
// repeatedGet reports the first time url is fetched again within a second, a sign
// the response should be cached. It fires once per url to avoid log spam.
func repeatedGet(url string, now time.Time) bool {
httpSeenMu.Lock()
defer httpSeenMu.Unlock()
a, seen := httpSeen[url]
warn := seen && !a.warned && now.Sub(a.last) < time.Second
httpSeen[url] = httpAccess{last: now, warned: a.warned || warn}
return warn
}
var _ Getters = (*HTTP)(nil)
// StringGetter sends string request