From cea8bcc9bb9495dcab6ea9b42a1adfd2b206c139 Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Fri, 17 Dec 2021 09:56:41 -0800 Subject: [PATCH] Remove the "URI" RPC client. (#7474) 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. --- CHANGELOG_PENDING.md | 1 + rpc/jsonrpc/client/args_test.go | 39 ------------ rpc/jsonrpc/client/encode.go | 46 --------------- rpc/jsonrpc/client/http_uri_client.go | 85 --------------------------- rpc/jsonrpc/jsonrpc_test.go | 30 ---------- 5 files changed, 1 insertion(+), 200 deletions(-) delete mode 100644 rpc/jsonrpc/client/args_test.go delete mode 100644 rpc/jsonrpc/client/encode.go delete mode 100644 rpc/jsonrpc/client/http_uri_client.go diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index e06bf4c06..099e6fcf0 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -27,6 +27,7 @@ Special thanks to external contributors on this release: - Go API + - [rpc] \#7474 Remove the "URI" RPC client. (@creachadair) - [libs/pubsub] \#7451 Internalize the pubsub packages. (@creachadair) - [libs/sync] \#7450 Internalize and remove the library. (@creachadair) - [libs/async] \#7449 Move library to internal. (@creachadair) diff --git a/rpc/jsonrpc/client/args_test.go b/rpc/jsonrpc/client/args_test.go deleted file mode 100644 index 2506f3073..000000000 --- a/rpc/jsonrpc/client/args_test.go +++ /dev/null @@ -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) - } -} diff --git a/rpc/jsonrpc/client/encode.go b/rpc/jsonrpc/client/encode.go deleted file mode 100644 index e085f51a2..000000000 --- a/rpc/jsonrpc/client/encode.go +++ /dev/null @@ -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 -} diff --git a/rpc/jsonrpc/client/http_uri_client.go b/rpc/jsonrpc/client/http_uri_client.go deleted file mode 100644 index 061622942..000000000 --- a/rpc/jsonrpc/client/http_uri_client.go +++ /dev/null @@ -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) -} diff --git a/rpc/jsonrpc/jsonrpc_test.go b/rpc/jsonrpc/jsonrpc_test.go index 3426c48b8..626959b01 100644 --- a/rpc/jsonrpc/jsonrpc_test.go +++ b/rpc/jsonrpc/jsonrpc_test.go @@ -273,11 +273,6 @@ func TestServersAndClientsBasic(t *testing.T) { ctx, cancel := context.WithCancel(bctx) defer cancel() - cl1, err := client.NewURI(addr) - require.Nil(t, err) - fmt.Printf("=== testing server on %s using URI client", addr) - testWithHTTPClient(ctx, t, cl1) - cl2, err := client.New(addr) require.Nil(t, err) fmt.Printf("=== testing server on %s using JSONRPC client", addr) @@ -295,31 +290,6 @@ func TestServersAndClientsBasic(t *testing.T) { } } -func TestHexStringArg(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cl, err := client.NewURI(tcpAddr) - require.Nil(t, err) - // should NOT be handled as hex - val := "0xabc" - got, err := echoViaHTTP(ctx, cl, val) - require.Nil(t, err) - assert.Equal(t, got, val) -} - -func TestQuotedStringArg(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - cl, err := client.NewURI(tcpAddr) - require.Nil(t, err) - // should NOT be unquoted - val := "\"abc\"" - got, err := echoViaHTTP(ctx, cl, val) - require.Nil(t, err) - assert.Equal(t, got, val) -} - func TestWSNewWSRPCFunc(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel()