|
|
@ -3,10 +3,12 @@ package jsonrpc
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"encoding/json"
|
|
|
|
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"net/url"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// Client json rpc client
|
|
|
|
// Client json rpc client
|
|
|
@ -30,19 +32,37 @@ type request struct {
|
|
|
|
type response struct {
|
|
|
|
type response struct {
|
|
|
|
Version string `json:"jsonrpc"`
|
|
|
|
Version string `json:"jsonrpc"`
|
|
|
|
Result json.RawMessage `json:"result"`
|
|
|
|
Result json.RawMessage `json:"result"`
|
|
|
|
Error *errorObj `json:"error"`
|
|
|
|
Error *Error `json:"error"`
|
|
|
|
ID uint64 `json:"id"`
|
|
|
|
ID uint64 `json:"id"`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type errorObj struct {
|
|
|
|
// Error rpc error
|
|
|
|
|
|
|
|
type Error struct {
|
|
|
|
Code int `json:"code"`
|
|
|
|
Code int `json:"code"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
Data interface{} `json:"data"`
|
|
|
|
Data interface{} `json:"data"`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (e *Error) Error() string {
|
|
|
|
|
|
|
|
return fmt.Sprintf("%d: %s", e.Code, e.Message)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewClient create a new jsonrpc client
|
|
|
|
// NewClient create a new jsonrpc client
|
|
|
|
func NewClient(url string) (*Client, error) {
|
|
|
|
func NewClient(uri string) (*Client, error) {
|
|
|
|
return &Client{URL: url, HTTPClient: http.DefaultClient}, nil
|
|
|
|
u, err := url.Parse(uri)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if u.Scheme != "http" && u.Scheme != "https" {
|
|
|
|
|
|
|
|
return nil, errors.New("only http/https supported")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if u.Host == "" {
|
|
|
|
|
|
|
|
return nil, errors.New("invalid uri")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return &Client{URL: uri, HTTPClient: http.DefaultClient}, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (c *Client) nextID() uint64 {
|
|
|
|
func (c *Client) nextID() uint64 {
|
|
|
@ -93,10 +113,6 @@ func (c *Client) Call(method string, args interface{}, reply interface{}) error
|
|
|
|
|
|
|
|
|
|
|
|
defer resp.Body.Close()
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
|
|
|
|
return fmt.Errorf("http error: %s", resp.Status)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data, err = ioutil.ReadAll(resp.Body)
|
|
|
|
data, err = ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
@ -109,11 +125,21 @@ func (c *Client) Call(method string, args interface{}, reply interface{}) error
|
|
|
|
var res response
|
|
|
|
var res response
|
|
|
|
|
|
|
|
|
|
|
|
if err = json.Unmarshal(data, &res); err != nil {
|
|
|
|
if err = json.Unmarshal(data, &res); err != nil {
|
|
|
|
|
|
|
|
// non 200 response without valid json response
|
|
|
|
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
|
|
|
|
return fmt.Errorf("http error: %s", resp.Status)
|
|
|
|
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if res.Error != nil {
|
|
|
|
// non 200 response with valid json response
|
|
|
|
return fmt.Errorf("%d: %s", res.Error.Code, res.Error.Message)
|
|
|
|
if res.ID == r.ID && res.Error != nil {
|
|
|
|
|
|
|
|
return res.Error
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// non 200 response without valid json response
|
|
|
|
|
|
|
|
if res.ID == r.ID && resp.StatusCode != http.StatusOK {
|
|
|
|
|
|
|
|
return fmt.Errorf("http error: %s", resp.Status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return json.Unmarshal(res.Result, &reply)
|
|
|
|
return json.Unmarshal(res.Result, &reply)
|
|
|
|