mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 14:21:14 +00:00
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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user