mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 14:21:14 +00:00
rpc/client: take context as first param (#5347)
Closes #5145 also applies to light/client
This commit is contained in:
@@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@@ -78,12 +79,12 @@ func (u parsedURL) GetTrimmedURL() string {
|
||||
// HTTPClient is a common interface for JSON-RPC HTTP clients.
|
||||
type HTTPClient interface {
|
||||
// Call calls the given method with the params and returns a result.
|
||||
Call(method string, params map[string]interface{}, result interface{}) (interface{}, error)
|
||||
Call(ctx context.Context, method string, params map[string]interface{}, result interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
// Caller implementers can facilitate calling the JSON-RPC endpoint.
|
||||
type Caller interface {
|
||||
Call(method string, params map[string]interface{}, result interface{}) (interface{}, error)
|
||||
Call(ctx context.Context, method string, params map[string]interface{}, result interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
@@ -151,7 +152,9 @@ func NewWithHTTPClient(remote string, client *http.Client) (*Client, error) {
|
||||
|
||||
// Call issues a POST HTTP request. Requests are JSON encoded. Content-Type:
|
||||
// text/json.
|
||||
func (c *Client) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) {
|
||||
func (c *Client) Call(ctx context.Context, method string,
|
||||
params map[string]interface{}, result interface{}) (interface{}, error) {
|
||||
|
||||
id := c.nextRequestID()
|
||||
|
||||
request, err := types.MapToRequest(id, method, params)
|
||||
@@ -165,7 +168,7 @@ func (c *Client) Call(method string, params map[string]interface{}, result inter
|
||||
}
|
||||
|
||||
requestBuf := bytes.NewBuffer(requestBytes)
|
||||
httpRequest, err := http.NewRequest(http.MethodPost, c.address, requestBuf)
|
||||
httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, c.address, requestBuf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
@@ -195,7 +198,7 @@ func (c *Client) NewRequestBatch() *RequestBatch {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) sendBatch(requests []*jsonRPCBufferedRequest) ([]interface{}, error) {
|
||||
func (c *Client) sendBatch(ctx context.Context, requests []*jsonRPCBufferedRequest) ([]interface{}, error) {
|
||||
reqs := make([]types.RPCRequest, 0, len(requests))
|
||||
results := make([]interface{}, 0, len(requests))
|
||||
for _, req := range requests {
|
||||
@@ -206,12 +209,12 @@ func (c *Client) sendBatch(requests []*jsonRPCBufferedRequest) ([]interface{}, e
|
||||
// serialize the array of requests into a single JSON object
|
||||
requestBytes, err := json.Marshal(reqs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal requests: %w", err)
|
||||
return nil, fmt.Errorf("json marshal: %w", err)
|
||||
}
|
||||
|
||||
httpRequest, err := http.NewRequest(http.MethodPost, c.address, bytes.NewBuffer(requestBytes))
|
||||
httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, c.address, bytes.NewBuffer(requestBytes))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
return nil, fmt.Errorf("new request: %w", err)
|
||||
}
|
||||
httpRequest.Header.Set("Content-Type", "text/json")
|
||||
if c.username != "" || c.password != "" {
|
||||
@@ -219,13 +222,13 @@ func (c *Client) sendBatch(requests []*jsonRPCBufferedRequest) ([]interface{}, e
|
||||
}
|
||||
httpResponse, err := c.client.Do(httpRequest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("post failed: %w", err)
|
||||
return nil, fmt.Errorf("post: %w", err)
|
||||
}
|
||||
defer httpResponse.Body.Close()
|
||||
|
||||
responseBytes, err := ioutil.ReadAll(httpResponse.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response body: %w", err)
|
||||
return nil, fmt.Errorf("read response body: %w", err)
|
||||
}
|
||||
|
||||
// collect ids to check responses IDs in unmarshalResponseBytesArray
|
||||
@@ -293,18 +296,19 @@ func (b *RequestBatch) clear() int {
|
||||
// Send will attempt to send the current batch of enqueued requests, and then
|
||||
// will clear out the requests once done. On success, this returns the
|
||||
// deserialized list of results from each of the enqueued requests.
|
||||
func (b *RequestBatch) Send() ([]interface{}, error) {
|
||||
func (b *RequestBatch) Send(ctx context.Context) ([]interface{}, error) {
|
||||
b.mtx.Lock()
|
||||
defer func() {
|
||||
b.clear()
|
||||
b.mtx.Unlock()
|
||||
}()
|
||||
return b.client.sendBatch(b.requests)
|
||||
return b.client.sendBatch(ctx, b.requests)
|
||||
}
|
||||
|
||||
// Call enqueues a request to call the given RPC method with the specified
|
||||
// parameters, in the same way that the `Client.Call` function would.
|
||||
func (b *RequestBatch) Call(
|
||||
_ context.Context,
|
||||
method string,
|
||||
params map[string]interface{},
|
||||
result interface{},
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
types "github.com/tendermint/tendermint/rpc/jsonrpc/types"
|
||||
)
|
||||
@@ -49,21 +51,34 @@ func NewURI(remote string) (*URIClient, error) {
|
||||
}
|
||||
|
||||
// Call issues a POST form HTTP request.
|
||||
func (c *URIClient) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) {
|
||||
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)
|
||||
}
|
||||
|
||||
resp, err := c.client.PostForm(c.address+"/"+method, values)
|
||||
req, err := http.NewRequestWithContext(
|
||||
ctx,
|
||||
http.MethodPost,
|
||||
c.address+"/"+method,
|
||||
strings.NewReader(values.Encode()),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("post form failed: %w", err)
|
||||
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 := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response body: %w", err)
|
||||
return nil, fmt.Errorf("read response body: %w", err)
|
||||
}
|
||||
|
||||
return unmarshalResponseBytes(responseBytes, URIClientRequestID, result)
|
||||
|
||||
@@ -37,6 +37,10 @@ const (
|
||||
testVal = "acbd"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
type ResultEcho struct {
|
||||
Value string `json:"value"`
|
||||
}
|
||||
@@ -156,7 +160,7 @@ func echoViaHTTP(cl client.Caller, val string) (string, error) {
|
||||
"arg": val,
|
||||
}
|
||||
result := new(ResultEcho)
|
||||
if _, err := cl.Call("echo", params, result); err != nil {
|
||||
if _, err := cl.Call(ctx, "echo", params, result); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result.Value, nil
|
||||
@@ -167,7 +171,7 @@ func echoIntViaHTTP(cl client.Caller, val int) (int, error) {
|
||||
"arg": val,
|
||||
}
|
||||
result := new(ResultEchoInt)
|
||||
if _, err := cl.Call("echo_int", params, result); err != nil {
|
||||
if _, err := cl.Call(ctx, "echo_int", params, result); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.Value, nil
|
||||
@@ -178,7 +182,7 @@ func echoBytesViaHTTP(cl client.Caller, bytes []byte) ([]byte, error) {
|
||||
"arg": bytes,
|
||||
}
|
||||
result := new(ResultEchoBytes)
|
||||
if _, err := cl.Call("echo_bytes", params, result); err != nil {
|
||||
if _, err := cl.Call(ctx, "echo_bytes", params, result); err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return result.Value, nil
|
||||
@@ -189,7 +193,7 @@ func echoDataBytesViaHTTP(cl client.Caller, bytes tmbytes.HexBytes) (tmbytes.Hex
|
||||
"arg": bytes,
|
||||
}
|
||||
result := new(ResultEchoDataBytes)
|
||||
if _, err := cl.Call("echo_data_bytes", params, result); err != nil {
|
||||
if _, err := cl.Call(ctx, "echo_data_bytes", params, result); err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return result.Value, nil
|
||||
|
||||
Reference in New Issue
Block a user