github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/rpc/lib/jsonrpc/client.go (about) 1 package jsonrpc 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "net/http" 9 "net/url" 10 "reflect" 11 12 "github.com/hyperledger/burrow/rpc/lib/types" 13 "github.com/pkg/errors" 14 ) 15 16 // HTTPClient is a common interface for Client and URIClient. 17 type HTTPClient interface { 18 Call(method string, params interface{}, result interface{}) error 19 } 20 21 // Client takes params as a slice 22 type Client struct { 23 address string 24 client http.Client 25 } 26 27 // NewClient returns a Client pointed at the given address. 28 func NewClient(remote string) *Client { 29 return &Client{ 30 address: remote, 31 } 32 } 33 34 func (c *Client) Call(method string, params interface{}, result interface{}) error { 35 request, err := types.NewRequest("jsonrpc-client", method, params) 36 if err != nil { 37 return err 38 } 39 bs, err := json.Marshal(request) 40 if err != nil { 41 return err 42 } 43 buf := bytes.NewBuffer(bs) 44 response, err := c.client.Post(c.address, "application/json", buf) 45 if err != nil { 46 return err 47 } 48 defer response.Body.Close() 49 50 bs, err = ioutil.ReadAll(response.Body) 51 if err != nil { 52 return err 53 } 54 return unmarshalResponseBytes(bs, result) 55 } 56 57 // URI takes params as a map 58 type URIClient struct { 59 address string 60 client http.Client 61 } 62 63 func NewURIClient(remote string) *URIClient { 64 return &URIClient{ 65 address: remote, 66 } 67 } 68 69 func (c *URIClient) Call(method string, params interface{}, result interface{}) error { 70 values, err := argsToURLValues(params.(map[string]interface{})) 71 if err != nil { 72 return err 73 } 74 // log.Info(Fmt("URI request to %v (%v): %v", c.address, method, values)) 75 resp, err := c.client.PostForm(c.address+"/"+method, values) 76 if err != nil { 77 return err 78 } 79 defer resp.Body.Close() // nolint: errcheck 80 81 responseBytes, err := ioutil.ReadAll(resp.Body) 82 if err != nil { 83 return err 84 } 85 return unmarshalResponseBytes(responseBytes, result) 86 } 87 88 func unmarshalResponseBytes(responseBytes []byte, result interface{}) error { 89 var err error 90 response := &types.RPCResponse{} 91 err = json.Unmarshal(responseBytes, response) 92 if err != nil { 93 return errors.Errorf("Error unmarshalling rpc response: %v", err) 94 } 95 if response.Error != nil { 96 return response.Error 97 } 98 // Unmarshal the RawMessage into the result. 99 err = json.Unmarshal(response.Result, result) 100 if err != nil { 101 return errors.Errorf("error unmarshalling rpc response result: %v", err) 102 } 103 return nil 104 } 105 106 func argsToURLValues(args map[string]interface{}) (url.Values, error) { 107 values := make(url.Values) 108 if len(args) == 0 { 109 return values, nil 110 } 111 err := argsToJSON(args) 112 if err != nil { 113 return nil, err 114 } 115 for key, val := range args { 116 values.Set(key, val.(string)) 117 } 118 return values, nil 119 } 120 121 func argsToJSON(args map[string]interface{}) error { 122 for k, v := range args { 123 rt := reflect.TypeOf(v) 124 isByteSlice := rt.Kind() == reflect.Slice && rt.Elem().Kind() == reflect.Uint8 125 if isByteSlice { 126 bs := reflect.ValueOf(v).Bytes() 127 args[k] = fmt.Sprintf("0x%X", bs) 128 continue 129 } 130 131 data, err := json.Marshal(v) 132 if err != nil { 133 return err 134 } 135 args[k] = string(data) 136 } 137 return nil 138 }