From 80900fd64846e46a2867a9b9e31cd95492fd9ccb Mon Sep 17 00:00:00 2001 From: Rishabh Vaish Date: Wed, 8 Apr 2026 03:36:38 -0700 Subject: [PATCH] chore: fix response body leak on 404 and hoist LoadLocation (#28612) --- tariff/pun.go | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tariff/pun.go b/tariff/pun.go index fa86988e2..a60f0fd88 100644 --- a/tariff/pun.go +++ b/tariff/pun.go @@ -4,6 +4,7 @@ import ( "archive/zip" "bytes" "encoding/xml" + "errors" "fmt" "net/http" "net/http/cookiejar" @@ -19,6 +20,12 @@ import ( "github.com/evcc-io/evcc/util/request" ) +// ErrPunDataNotAvailable indicates that GME has not yet published prices for the requested day. +var ErrPunDataNotAvailable = errors.New("PUN data not available") + +// romeLocation is resolved once at package init to avoid repeated filesystem lookups. +var romeLocation *time.Location + type Pun struct { *embed log *util.Logger @@ -46,6 +53,7 @@ var _ api.Tariff = (*Pun)(nil) func init() { registry.Add("pun", NewPunFromConfig) + romeLocation, _ = time.LoadLocation("Europe/Rome") } func NewPunFromConfig(other map[string]any) (api.Tariff, error) { @@ -137,9 +145,14 @@ func (t *Pun) getData(day time.Time) (api.Rates, error) { } resp, err := client.Do(req) - if err != nil || resp.StatusCode == http.StatusNotFound { + if err != nil { return nil, err } + defer resp.Body.Close() + + if resp.StatusCode == http.StatusNotFound { + return nil, fmt.Errorf("%w: %s", ErrPunDataNotAvailable, day.Format("2006-01-02")) + } body, err := request.ReadBody(resp) if err != nil { @@ -193,17 +206,12 @@ func (t *Pun) getData(day time.Time) (api.Rates, error) { date = date.AddDate(0, 0, -1) } - location, err := time.LoadLocation("Europe/Rome") - if err != nil { - return nil, fmt.Errorf("load location: %w", err) - } - price, err := strconv.ParseFloat(strings.ReplaceAll(p.PUN, ",", "."), 64) if err != nil { return nil, fmt.Errorf("parse price: %w", err) } - ts := time.Date(date.Year(), date.Month(), date.Day(), hour-1, 0, 0, 0, location) + ts := time.Date(date.Year(), date.Month(), date.Day(), hour-1, 0, 0, 0, romeLocation) ar := api.Rate{ Start: ts, End: ts.Add(time.Hour),