The JSON-RPC endpoint accepts requests via URL (GET) and JSON (POST). There is no real point in having client libraries for both modes. A search of the SDK and on GitHub suggests that most usage is via the JSON client (via the New constructor) or websocket (NewWS), and the only uses I found of the NewURI client constructor are in copies of our own test code. This does not change the functionalitiy of the server, so curl and other URL-based clients in other languages will still function as before.pull/7477/head
@ -1,39 +0,0 @@ | |||||
package client | |||||
import ( | |||||
"testing" | |||||
"github.com/stretchr/testify/assert" | |||||
"github.com/stretchr/testify/require" | |||||
) | |||||
type Tx []byte | |||||
type Foo struct { | |||||
Bar int | |||||
Baz string | |||||
} | |||||
func TestArgToJSON(t *testing.T) { | |||||
assert := assert.New(t) | |||||
require := require.New(t) | |||||
cases := []struct { | |||||
input interface{} | |||||
expected string | |||||
}{ | |||||
{[]byte("1234"), "0x31323334"}, | |||||
{Tx("654"), "0x363534"}, | |||||
{Foo{7, "hello"}, `{"Bar":"7","Baz":"hello"}`}, | |||||
} | |||||
for i, tc := range cases { | |||||
args := map[string]interface{}{"data": tc.input} | |||||
err := argsToJSON(args) | |||||
require.Nil(err, "%d: %+v", i, err) | |||||
require.Equal(1, len(args), "%d", i) | |||||
data, ok := args["data"].(string) | |||||
require.True(ok, "%d: %#v", i, args["data"]) | |||||
assert.Equal(tc.expected, data, "%d", i) | |||||
} | |||||
} |
@ -1,46 +0,0 @@ | |||||
package client | |||||
import ( | |||||
"fmt" | |||||
"net/url" | |||||
"reflect" | |||||
tmjson "github.com/tendermint/tendermint/libs/json" | |||||
) | |||||
func argsToURLValues(args map[string]interface{}) (url.Values, error) { | |||||
values := make(url.Values) | |||||
if len(args) == 0 { | |||||
return values, nil | |||||
} | |||||
err := argsToJSON(args) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
for key, val := range args { | |||||
values.Set(key, val.(string)) | |||||
} | |||||
return values, nil | |||||
} | |||||
func argsToJSON(args map[string]interface{}) error { | |||||
for k, v := range args { | |||||
rt := reflect.TypeOf(v) | |||||
isByteSlice := rt.Kind() == reflect.Slice && rt.Elem().Kind() == reflect.Uint8 | |||||
if isByteSlice { | |||||
bytes := reflect.ValueOf(v).Bytes() | |||||
args[k] = fmt.Sprintf("0x%X", bytes) | |||||
continue | |||||
} | |||||
data, err := tmjson.Marshal(v) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
args[k] = string(data) | |||||
} | |||||
return nil | |||||
} |
@ -1,85 +0,0 @@ | |||||
package client | |||||
import ( | |||||
"context" | |||||
"fmt" | |||||
"io" | |||||
"net/http" | |||||
"strings" | |||||
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" | |||||
) | |||||
const ( | |||||
// URIClientRequestID in a request ID used by URIClient | |||||
URIClientRequestID = rpctypes.JSONRPCIntID(-1) | |||||
) | |||||
// URIClient is a JSON-RPC client, which sends POST form HTTP requests to the | |||||
// remote server. | |||||
// | |||||
// URIClient is safe for concurrent use by multiple goroutines. | |||||
type URIClient struct { | |||||
address string | |||||
client *http.Client | |||||
} | |||||
var _ HTTPClient = (*URIClient)(nil) | |||||
// NewURI returns a new client. | |||||
// An error is returned on invalid remote. | |||||
// The function panics when remote is nil. | |||||
func NewURI(remote string) (*URIClient, error) { | |||||
parsedURL, err := newParsedURL(remote) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
httpClient, err := DefaultHTTPClient(remote) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
parsedURL.SetDefaultSchemeHTTP() | |||||
uriClient := &URIClient{ | |||||
address: parsedURL.GetTrimmedURL(), | |||||
client: httpClient, | |||||
} | |||||
return uriClient, nil | |||||
} | |||||
// Call issues a POST form HTTP request. | |||||
func (c *URIClient) Call(ctx context.Context, method string, | |||||
params map[string]interface{}, result interface{}) (interface{}, error) { | |||||
values, err := argsToURLValues(params) | |||||
if err != nil { | |||||
return nil, fmt.Errorf("failed to encode params: %w", err) | |||||
} | |||||
req, err := http.NewRequestWithContext( | |||||
ctx, | |||||
http.MethodPost, | |||||
c.address+"/"+method, | |||||
strings.NewReader(values.Encode()), | |||||
) | |||||
if err != nil { | |||||
return nil, fmt.Errorf("new request: %w", err) | |||||
} | |||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded") | |||||
resp, err := c.client.Do(req) | |||||
if err != nil { | |||||
return nil, fmt.Errorf("post: %w", err) | |||||
} | |||||
defer resp.Body.Close() | |||||
responseBytes, err := io.ReadAll(resp.Body) | |||||
if err != nil { | |||||
return nil, fmt.Errorf("read response body: %w", err) | |||||
} | |||||
return unmarshalResponseBytes(responseBytes, URIClientRequestID, result) | |||||
} |