mirror of
https://github.com/onedr0p/exportarr.git
synced 2026-02-06 10:57:32 +00:00
Add Panic Recovery & Logging to Client JSON Unmarshalling (#139)
This commit is contained in:
parent
fed7319e77
commit
73fbf8dfaf
@ -4,8 +4,10 @@ import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/onedr0p/exportarr/internal/config"
|
||||
"go.uber.org/zap"
|
||||
@ -62,6 +64,30 @@ func NewClient(config *config.Config) (*Client, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) unmarshalBody(b io.Reader, target interface{}) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// return recovered panic as error
|
||||
err = fmt.Errorf("Recovered from panic: %s", r)
|
||||
|
||||
log := zap.S()
|
||||
if zap.S().Level() == zap.DebugLevel {
|
||||
s := new(strings.Builder)
|
||||
_, copyErr := io.Copy(s, b)
|
||||
if copyErr != nil {
|
||||
zap.S().Errorw("Failed to copy body to string in recover",
|
||||
"error", err, "recover", r)
|
||||
}
|
||||
log = log.With("body", s.String())
|
||||
}
|
||||
log.Errorw("Recovered while unmarshalling response", "error", r)
|
||||
|
||||
}
|
||||
}()
|
||||
err = json.NewDecoder(b).Decode(target)
|
||||
return
|
||||
}
|
||||
|
||||
// DoRequest - Take a HTTP Request and return Unmarshaled data
|
||||
func (c *Client) DoRequest(endpoint string, target interface{}, queryParams ...map[string]string) error {
|
||||
values := c.URL.Query()
|
||||
@ -84,5 +110,5 @@ func (c *Client) DoRequest(endpoint string, target interface{}, queryParams ...m
|
||||
return fmt.Errorf("Failed to execute HTTP Request(%s): %w", url, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return json.NewDecoder(resp.Body).Decode(target)
|
||||
return c.unmarshalBody(resp.Body, target)
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@ -79,3 +80,36 @@ func TestDoRequest(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoRequest_PanicRecovery(t *testing.T) {
|
||||
require := require.New(t)
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ret := struct {
|
||||
TestField string
|
||||
TestField2 string
|
||||
}{
|
||||
TestField: "asdf",
|
||||
TestField2: "asdf2",
|
||||
}
|
||||
s, err := json.Marshal(ret)
|
||||
require.NoError(err)
|
||||
w.Write(s)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
c := &config.Config{
|
||||
URL: ts.URL,
|
||||
ApiVersion: "v3",
|
||||
}
|
||||
|
||||
client, err := NewClient(c)
|
||||
require.Nil(err, "NewClient should not return an error")
|
||||
require.NotNil(client, "NewClient should return a client")
|
||||
|
||||
err = client.DoRequest("test", nil)
|
||||
require.NotPanics(func() {
|
||||
require.Error(err, "DoRequest should return an error: %s", err)
|
||||
}, "DoRequest should recover from a panic")
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user