Fix memory leaks due to not closing http request body (#997)

This commit is contained in:
andig 2021-05-10 21:58:04 +02:00 • committed by GitHub
parent 4828d197d6
commit 62052e0159
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 28 deletions

View file

@ -181,8 +181,9 @@ func (evse *EVSEWifi) Enabled() (bool, error) {
return params.EvseState, err
}
// checkError checks for EVSE error response with HTTP 200 status
func (evse *EVSEWifi) checkError(b []byte, err error) error {
// get executes GET request and checks for EVSE error response
func (evse *EVSEWifi) get(uri string) error {
b, err := evse.GetBody(uri)
if err == nil && !strings.HasPrefix(string(b), evseSuccess) {
err = errors.New(string(b))
}
@ -200,14 +201,14 @@ func (evse *EVSEWifi) Enable(enable bool) error {
}
url = fmt.Sprintf("%s?current=%d", evse.apiURL(evseSetCurrent), current)
}
return evse.checkError(evse.GetBody(url))
return evse.get(url)
}
// MaxCurrent implements the api.Charger interface
func (evse *EVSEWifi) MaxCurrent(current int64) error {
evse.current = current
url := fmt.Sprintf("%s?current=%d", evse.apiURL(evseSetCurrent), current)
return evse.checkError(evse.GetBody(url))
return evse.get(url)
}
var _ api.ChargeTimer = (*EVSEWifi)(nil)

View file

@ -180,12 +180,8 @@ func (v *Identity) fetchToken(emobility bool) (tokenResponse, error) {
}
req, err = request.New(http.MethodPost, "https://login.porsche.com/as/token.oauth2", strings.NewReader(dataAPIToken.Encode()), request.URLEncoding)
if err == nil {
resp, err = v.Client.Do(req)
if err == nil {
err = request.DecodeJSON(resp, &pr)
}
err = v.DoJSON(req, &pr)
}
if pr.AccessToken == "" || pr.ExpiresIn == 0 {
@ -212,7 +208,6 @@ func (v *Identity) FindVehicle(accessTokens AccessTokens, vin string) (Vehicle,
})
var vehicles []VehicleResponse
if err == nil {
err = v.DoJSON(req, &vehicles)
}

View file

@ -10,6 +10,7 @@ import (
"log"
"math/rand"
"net/http"
"net/http/pprof"
"os"
"strings"
"time"
@ -17,6 +18,7 @@ import (
"github.com/andig/evcc/soc/server/auth"
"github.com/andig/evcc/util"
"github.com/dgrijalva/jwt-go"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/crypto/acme/autocert"
"golang.org/x/oauth2"
"golang.org/x/oauth2/github"
@ -214,6 +216,14 @@ func Run() {
mux.HandleFunc("/login", handleLogin)
mux.HandleFunc("/callback", handleCallback)
mux.Handle("/metrics", promhttp.Handler())
mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
// mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
// mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
// mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
s := &http.Server{
Addr: ":http",
Handler: mux,

View file

@ -1,8 +1,6 @@
package request
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
@ -67,9 +65,6 @@ func ReadBody(resp *http.Response) ([]byte, error) {
return []byte{}, err
}
// maintain body after reading
resp.Body = io.NopCloser(bytes.NewBuffer(b))
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return b, StatusError{resp: resp}
}
@ -77,15 +72,6 @@ func ReadBody(resp *http.Response) ([]byte, error) {
return b, nil
}
// DecodeJSON reads HTTP response and decodes JSON body if error is nil
func DecodeJSON(resp *http.Response, res interface{}) error {
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return StatusError{resp: resp}
}
return json.NewDecoder(resp.Body).Decode(&res)
}
// New builds and executes HTTP request and returns the response
func New(method, uri string, data io.Reader, headers ...map[string]string) (*http.Request, error) {
req, err := http.NewRequest(method, uri, data)

View file

@ -1,6 +1,7 @@
package request
import (
"encoding/json"
"net/http"
"time"
@ -47,20 +48,31 @@ func (r *Helper) GetBody(url string) ([]byte, error) {
return body, err
}
// DoJSON executes HTTP request and decodes JSON response
// decodeJSON reads HTTP response and decodes JSON body if error is nil
func decodeJSON(resp *http.Response, res interface{}) error {
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return StatusError{resp: resp}
}
return json.NewDecoder(resp.Body).Decode(&res)
}
// DoJSON executes HTTP request and decodes JSON response. It returns a StatusError on response codes other than HTTP 2xx.
func (r *Helper) DoJSON(req *http.Request, res interface{}) error {
resp, err := r.Do(req)
if err == nil {
err = DecodeJSON(resp, &res)
defer resp.Body.Close()
err = decodeJSON(resp, &res)
}
return err
}
// GetJSON executes HTTP GET request and decodes JSON response
// GetJSON executes HTTP GET request and decodes JSON response. It returns a StatusError on response codes other than HTTP 2xx.
func (r *Helper) GetJSON(url string, res interface{}) error {
resp, err := r.Get(url)
if err == nil {
err = DecodeJSON(resp, &res)
defer resp.Body.Close()
err = decodeJSON(resp, &res)
}
return err
}