Merge pull request #85 from lbryio/lbryinc-errors

Lbryinc errors
This commit is contained in:
Andrey Beletsky 2021-02-23 00:37:59 +07:00 committed by GitHub
commit 29773829af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 40 deletions

View file

@ -2,7 +2,7 @@ os: linux
dist: xenial dist: xenial
language: go language: go
go: go:
- 1.11.x - 1.15.x
env: env:
global: global:

View file

@ -46,6 +46,15 @@ type APIResponse struct {
Data *ResponseData `json:"data"` Data *ResponseData `json:"data"`
} }
// APIError wraps errors returned by LBRY API server to discern them from other kinds (like http errors).
type APIError struct {
Err error
}
func (e APIError) Error() string {
return fmt.Sprintf("api error: %v", e.Err)
}
// ResponseData is a map containing parsed json response. // ResponseData is a map containing parsed json response.
type ResponseData map[string]interface{} type ResponseData map[string]interface{}
@ -110,6 +119,9 @@ func (c Client) doCall(url string, payload string) ([]byte, error) {
if err != nil { if err != nil {
return body, err return body, err
} }
if r.StatusCode >= 500 {
return body, fmt.Errorf("server returned non-OK status: %v", r.StatusCode)
}
defer r.Body.Close() defer r.Body.Close()
return ioutil.ReadAll(r.Body) return ioutil.ReadAll(r.Body)
} }
@ -133,16 +145,17 @@ func (c Client) Call(object, method string, params map[string]interface{}) (Resp
return rd, err return rd, err
} }
if !ar.Success { if !ar.Success {
return rd, errors.New(*ar.Error) return rd, APIError{errors.New(*ar.Error)}
} }
return *ar.Data, err return *ar.Data, err
} }
// UserMe returns user details for the user associated with the current auth_token // UserMe returns user details for the user associated with the current auth_token.
func (c Client) UserMe() (ResponseData, error) { func (c Client) UserMe() (ResponseData, error) {
return c.Call(userObjectPath, userMeMethod, map[string]interface{}{}) return c.Call(userObjectPath, userMeMethod, map[string]interface{}{})
} }
// UserHasVerifiedEmail calls has_verified_email method.
func (c Client) UserHasVerifiedEmail() (ResponseData, error) { func (c Client) UserHasVerifiedEmail() (ResponseData, error) {
return c.Call(userObjectPath, userHasVerifiedEmailMethod, map[string]interface{}{}) return c.Call(userObjectPath, userHasVerifiedEmailMethod, map[string]interface{}{})
} }

View file

@ -7,42 +7,26 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestUserMeWrongToken(t *testing.T) { func launchDummyServer(lastReq **http.Request, path, response string, status int) *httptest.Server {
c := NewClient("abc", nil)
r, err := c.UserMe()
require.NotNil(t, err)
assert.Equal(t, "could not authenticate user", err.Error())
assert.Nil(t, r)
}
func TestUserHasVerifiedEmailWrongToken(t *testing.T) {
c := NewClient("abc", nil)
r, err := c.UserHasVerifiedEmail()
require.NotNil(t, err)
assert.Equal(t, "could not authenticate user", err.Error())
assert.Nil(t, r)
}
func launchDummyServer(lastReq **http.Request, path, response string) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if lastReq != nil {
*lastReq = &*r *lastReq = &*r
}
if r.URL.Path != path { if r.URL.Path != path {
fmt.Printf("path doesn't match: %v != %v", r.URL.Path, path) fmt.Printf("path doesn't match: %v != %v", r.URL.Path, path)
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
} else { } else {
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK) w.WriteHeader(status)
w.Write([]byte(response)) w.Write([]byte(response))
} }
})) }))
} }
func TestUserMe(t *testing.T) { func TestUserMe(t *testing.T) {
var req *http.Request ts := launchDummyServer(nil, makeMethodPath(userObjectPath, userMeMethod), userMeResponse, http.StatusOK)
ts := launchDummyServer(&req, makeMethodPath(userObjectPath, userMeMethod), userMeResponse)
defer ts.Close() defer ts.Close()
c := NewClient("realToken", &ClientOpts{ServerAddress: ts.URL}) c := NewClient("realToken", &ClientOpts{ServerAddress: ts.URL})
@ -52,8 +36,7 @@ func TestUserMe(t *testing.T) {
} }
func TestUserHasVerifiedEmail(t *testing.T) { func TestUserHasVerifiedEmail(t *testing.T) {
var req *http.Request ts := launchDummyServer(nil, makeMethodPath(userObjectPath, userHasVerifiedEmailMethod), userHasVerifiedEmailResponse, http.StatusOK)
ts := launchDummyServer(&req, makeMethodPath(userObjectPath, userHasVerifiedEmailMethod), userHasVerifiedEmailResponse)
defer ts.Close() defer ts.Close()
c := NewClient("realToken", &ClientOpts{ServerAddress: ts.URL}) c := NewClient("realToken", &ClientOpts{ServerAddress: ts.URL})
@ -65,7 +48,7 @@ func TestUserHasVerifiedEmail(t *testing.T) {
func TestRemoteIP(t *testing.T) { func TestRemoteIP(t *testing.T) {
var req *http.Request var req *http.Request
ts := launchDummyServer(&req, makeMethodPath(userObjectPath, userMeMethod), userMeResponse) ts := launchDummyServer(&req, makeMethodPath(userObjectPath, userMeMethod), userMeResponse, http.StatusOK)
defer ts.Close() defer ts.Close()
c := NewClient("realToken", &ClientOpts{ServerAddress: ts.URL, RemoteIP: "8.8.8.8"}) c := NewClient("realToken", &ClientOpts{ServerAddress: ts.URL, RemoteIP: "8.8.8.8"})
@ -74,6 +57,34 @@ func TestRemoteIP(t *testing.T) {
assert.Equal(t, []string{"8.8.8.8"}, req.Header["X-Forwarded-For"]) assert.Equal(t, []string{"8.8.8.8"}, req.Header["X-Forwarded-For"])
} }
func TestWrongToken(t *testing.T) {
c := NewClient("zcasdasc", nil)
r, err := c.UserHasVerifiedEmail()
assert.Nil(t, r)
assert.EqualError(t, err, "api error: could not authenticate user")
assert.ErrorAs(t, err, &APIError{})
}
func TestHTTPError(t *testing.T) {
c := NewClient("zcasdasc", &ClientOpts{ServerAddress: "http://lolcathost"})
r, err := c.UserHasVerifiedEmail()
assert.Nil(t, r)
assert.EqualError(t, err, `Post "http://lolcathost/user/has_verified_email": dial tcp: lookup lolcathost: no such host`)
}
func TestGatewayError(t *testing.T) {
var req *http.Request
ts := launchDummyServer(&req, makeMethodPath(userObjectPath, userHasVerifiedEmailMethod), "", http.StatusBadGateway)
defer ts.Close()
c := NewClient("zcasdasc", &ClientOpts{ServerAddress: ts.URL})
r, err := c.UserHasVerifiedEmail()
assert.Nil(t, r)
assert.EqualError(t, err, `server returned non-OK status: 502`)
}
const userMeResponse = `{ const userMeResponse = `{
"success": true, "success": true,
"error": null, "error": null,

4
go.mod
View file

@ -34,7 +34,7 @@ require (
github.com/smartystreets/assertions v1.0.1 // indirect github.com/smartystreets/assertions v1.0.1 // indirect
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect
github.com/spf13/cast v1.3.0 github.com/spf13/cast v1.3.0
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.7.0
github.com/ybbus/jsonrpc v0.0.0-20180411222309-2a548b7d822d github.com/ybbus/jsonrpc v0.0.0-20180411222309-2a548b7d822d
go.uber.org/atomic v1.4.0 go.uber.org/atomic v1.4.0
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc
@ -51,4 +51,4 @@ require (
gotest.tools v2.2.0+incompatible gotest.tools v2.2.0+incompatible
) )
go 1.13 go 1.15

10
go.sum
View file

@ -63,13 +63,10 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lbryio/lbry.go v1.1.2 h1:Dyxc+glT/rVWJwHfIf7vjlPYYbjzrQz5ARmJd5Hp69c=
github.com/lbryio/lbrycrd.go v0.0.0-20200203050410-e1076f12bf19 h1:/zWD8dVIl7bV1TdJWqPqy9tpqixzX2Qxgit48h3hQcY= github.com/lbryio/lbrycrd.go v0.0.0-20200203050410-e1076f12bf19 h1:/zWD8dVIl7bV1TdJWqPqy9tpqixzX2Qxgit48h3hQcY=
github.com/lbryio/lbrycrd.go v0.0.0-20200203050410-e1076f12bf19/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/lbryio/lbrycrd.go v0.0.0-20200203050410-e1076f12bf19/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/lbryio/ozzo-validation v0.0.0-20170323141101-d1008ad1fd04 h1:Nze+C2HbeKvhjI/kVn+9Poj/UuEW5sOQxcsxqO7L3GI= github.com/lbryio/ozzo-validation v0.0.0-20170323141101-d1008ad1fd04 h1:Nze+C2HbeKvhjI/kVn+9Poj/UuEW5sOQxcsxqO7L3GI=
github.com/lbryio/ozzo-validation v0.0.0-20170323141101-d1008ad1fd04/go.mod h1:fbG/dzobG8r95KzMwckXiLMHfFjZaBRQqC9hPs2XAQ4= github.com/lbryio/ozzo-validation v0.0.0-20170323141101-d1008ad1fd04/go.mod h1:fbG/dzobG8r95KzMwckXiLMHfFjZaBRQqC9hPs2XAQ4=
github.com/lbryio/types v0.0.0-20191009145016-1bb8107e04f8 h1:jSNW/rK6DQsz7Zh+iv1zR384PeQdHt0gS4hKY17tkuM=
github.com/lbryio/types v0.0.0-20191009145016-1bb8107e04f8/go.mod h1:CG3wsDv5BiVYQd5i1Jp7wGsaVyjZTJshqXeWMVKsISE=
github.com/lbryio/types v0.0.0-20201019032447-f0b4476ef386 h1:JOQkGpeCM9FWkEHRx+kRPqySPCXElNW1em1++7tVS4M= github.com/lbryio/types v0.0.0-20201019032447-f0b4476ef386 h1:JOQkGpeCM9FWkEHRx+kRPqySPCXElNW1em1++7tVS4M=
github.com/lbryio/types v0.0.0-20201019032447-f0b4476ef386/go.mod h1:CG3wsDv5BiVYQd5i1Jp7wGsaVyjZTJshqXeWMVKsISE= github.com/lbryio/types v0.0.0-20201019032447-f0b4476ef386/go.mod h1:CG3wsDv5BiVYQd5i1Jp7wGsaVyjZTJshqXeWMVKsISE=
github.com/lyoshenka/bencode v0.0.0-20180323155644-b7abd7672df5 h1:mG83tLXWSRdcXMWfkoumVwhcCbf3jHF9QKv/m37BkM0= github.com/lyoshenka/bencode v0.0.0-20180323155644-b7abd7672df5 h1:mG83tLXWSRdcXMWfkoumVwhcCbf3jHF9QKv/m37BkM0=
@ -109,8 +106,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/ybbus/jsonrpc v0.0.0-20180411222309-2a548b7d822d h1:tQo6hjclyv3RHUgZOl6iWb2Y44A/sN9bf9LAYfuioEg= github.com/ybbus/jsonrpc v0.0.0-20180411222309-2a548b7d822d h1:tQo6hjclyv3RHUgZOl6iWb2Y44A/sN9bf9LAYfuioEg=
github.com/ybbus/jsonrpc v0.0.0-20180411222309-2a548b7d822d/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= github.com/ybbus/jsonrpc v0.0.0-20180411222309-2a548b7d822d/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
@ -173,9 +170,10 @@ gopkg.in/nullbio/null.v6 v6.0.0-20161116030900-40264a2e6b79/go.mod h1:gWkaRU7CoX
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View file

@ -3,7 +3,7 @@ dist: trusty
language: go language: go
go: go:
- 1.10.3 - 1.15.x
script: script:
- ./build_and_test.sh - ./build_and_test.sh

View file

@ -24,9 +24,9 @@ const lbrycrdTestnet = "lbrycrd_testnet"
const lbrycrdRegtest = "lbrycrd_regtest" const lbrycrdRegtest = "lbrycrd_regtest"
var addressPrefixes = map[string][2]byte{ var addressPrefixes = map[string][2]byte{
lbrycrdMain: [2]byte{lbrycrdMainPubkeyPrefix, lbrycrdMainScriptPrefix}, lbrycrdMain: {lbrycrdMainPubkeyPrefix, lbrycrdMainScriptPrefix},
lbrycrdTestnet: [2]byte{lbrycrdTestnetPubkeyPrefix, lbrycrdTestnetScriptPrefix}, lbrycrdTestnet: {lbrycrdTestnetPubkeyPrefix, lbrycrdTestnetScriptPrefix},
lbrycrdRegtest: [2]byte{lbrycrdRegtestPubkeyPrefix, lbrycrdRegtestScriptPrefix}, lbrycrdRegtest: {lbrycrdRegtestPubkeyPrefix, lbrycrdRegtestScriptPrefix},
} }
func PrefixIsValid(address [addressLength]byte, blockchainName string) bool { func PrefixIsValid(address [addressLength]byte, blockchainName string) bool {