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.

133 lines
3.1 KiB

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