You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
3.3 KiB

  1. package rpcclient
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "io/ioutil"
  7. "net/http"
  8. "net/url"
  9. "strings"
  10. . "github.com/tendermint/go-common"
  11. "github.com/tendermint/go-rpc/types"
  12. "github.com/tendermint/go-wire"
  13. )
  14. // JSON rpc takes params as a slice
  15. type ClientJSONRPC struct {
  16. remote string
  17. }
  18. func NewClientJSONRPC(remote string) *ClientJSONRPC {
  19. return &ClientJSONRPC{remote}
  20. }
  21. func (c *ClientJSONRPC) Call(method string, params []interface{}, result interface{}) (interface{}, error) {
  22. return CallHTTP_JSONRPC(c.remote, method, params, result)
  23. }
  24. // URI takes params as a map
  25. type ClientURI struct {
  26. remote string
  27. }
  28. func NewClientURI(remote string) *ClientURI {
  29. if !strings.HasSuffix(remote, "/") {
  30. remote = remote + "/"
  31. }
  32. return &ClientURI{remote}
  33. }
  34. func (c *ClientURI) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) {
  35. return CallHTTP_URI(c.remote, method, params, result)
  36. }
  37. func CallHTTP_JSONRPC(remote string, method string, params []interface{}, result interface{}) (interface{}, error) {
  38. // Make request and get responseBytes
  39. request := rpctypes.RPCRequest{
  40. JSONRPC: "2.0",
  41. Method: method,
  42. Params: params,
  43. ID: "",
  44. }
  45. requestBytes := wire.JSONBytes(request)
  46. requestBuf := bytes.NewBuffer(requestBytes)
  47. log.Info(Fmt("RPC request to %v: %v", remote, string(requestBytes)))
  48. httpResponse, err := http.Post(remote, "text/json", requestBuf)
  49. if err != nil {
  50. return nil, err
  51. }
  52. defer httpResponse.Body.Close()
  53. responseBytes, err := ioutil.ReadAll(httpResponse.Body)
  54. if err != nil {
  55. return nil, err
  56. }
  57. log.Info(Fmt("RPC response: %v", string(responseBytes)))
  58. return unmarshalResponseBytes(responseBytes, result)
  59. }
  60. func CallHTTP_URI(remote string, method string, params map[string]interface{}, result interface{}) (interface{}, error) {
  61. values, err := argsToURLValues(params)
  62. if err != nil {
  63. return nil, err
  64. }
  65. log.Info(Fmt("URI request to %v: %v", remote, values))
  66. resp, err := http.PostForm(remote+method, values)
  67. if err != nil {
  68. return nil, err
  69. }
  70. defer resp.Body.Close()
  71. responseBytes, err := ioutil.ReadAll(resp.Body)
  72. if err != nil {
  73. return nil, err
  74. }
  75. return unmarshalResponseBytes(responseBytes, result)
  76. }
  77. //------------------------------------------------
  78. func unmarshalResponseBytes(responseBytes []byte, result interface{}) (interface{}, error) {
  79. // read response
  80. // if rpc/core/types is imported, the result will unmarshal
  81. // into the correct type
  82. var err error
  83. response := &rpctypes.RPCResponse{}
  84. err = json.Unmarshal(responseBytes, response)
  85. if err != nil {
  86. return nil, err
  87. }
  88. errorStr := response.Error
  89. if errorStr != "" {
  90. return nil, errors.New(errorStr)
  91. }
  92. // unmarshal the RawMessage into the result
  93. result = wire.ReadJSONPtr(result, *response.Result, &err)
  94. return result, err
  95. }
  96. func argsToURLValues(args map[string]interface{}) (url.Values, error) {
  97. values := make(url.Values)
  98. if len(args) == 0 {
  99. return values, nil
  100. }
  101. err := argsToJson(args)
  102. if err != nil {
  103. return nil, err
  104. }
  105. for key, val := range args {
  106. values.Set(key, val.(string))
  107. }
  108. return values, nil
  109. }
  110. func argsToJson(args map[string]interface{}) error {
  111. var n int
  112. var err error
  113. for k, v := range args {
  114. buf := new(bytes.Buffer)
  115. wire.WriteJSON(v, buf, &n, &err)
  116. if err != nil {
  117. return err
  118. }
  119. args[k] = buf.String()
  120. }
  121. return nil
  122. }