You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
2.2 KiB
Go
121 lines
2.2 KiB
Go
package jsonrpc
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
)
|
|
|
|
// Client json rpc client
|
|
type Client struct {
|
|
// URL is remote url, ex http://username:password@192.168.1.3:1001/jsonrpc
|
|
URL string
|
|
// http client, default is http.DefaultClient
|
|
HTTPClient *http.Client
|
|
id uint64
|
|
// Debug set to true, log the send/recevied http data
|
|
Debug bool
|
|
}
|
|
|
|
type request struct {
|
|
Version string `json:"jsonrpc"`
|
|
Method string `json:"method"`
|
|
Params interface{} `json:"params"`
|
|
ID uint64 `json:"id"`
|
|
}
|
|
|
|
type response struct {
|
|
Version string `json:"jsonrpc"`
|
|
Result json.RawMessage `json:"result"`
|
|
Error *errorObj `json:"error"`
|
|
ID uint64 `json:"id"`
|
|
}
|
|
|
|
type errorObj struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Data interface{} `json:"data"`
|
|
}
|
|
|
|
// NewClient create a new jsonrpc client
|
|
func NewClient(url string) (*Client, error) {
|
|
return &Client{URL: url, HTTPClient: http.DefaultClient}, nil
|
|
}
|
|
|
|
func (c *Client) nextID() uint64 {
|
|
c.id++
|
|
return c.id
|
|
}
|
|
|
|
// Call invoke a method with args and return reply
|
|
func (c *Client) Call(method string, args interface{}, reply interface{}) error {
|
|
client := c.HTTPClient
|
|
if client == nil {
|
|
client = http.DefaultClient
|
|
}
|
|
|
|
if args == nil {
|
|
args = []string{}
|
|
}
|
|
|
|
r := &request{
|
|
Version: "2.0",
|
|
Method: method,
|
|
Params: args,
|
|
ID: c.nextID(),
|
|
}
|
|
|
|
data, err := json.Marshal(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if c.Debug {
|
|
log.Println("send", string(data))
|
|
}
|
|
|
|
body := bytes.NewBuffer(data)
|
|
|
|
req, err := http.NewRequest("POST", c.URL, body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return fmt.Errorf("http error: %s", resp.Status)
|
|
}
|
|
|
|
data, err = ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if c.Debug {
|
|
log.Println("recevied", string(data))
|
|
}
|
|
|
|
var res response
|
|
|
|
if err = json.Unmarshal(data, &res); err != nil {
|
|
return err
|
|
}
|
|
|
|
if res.Error != nil {
|
|
return fmt.Errorf("%d: %s", res.Error.Code, res.Error.Message)
|
|
}
|
|
|
|
return json.Unmarshal(res.Result, &reply)
|
|
}
|