github.com/vipernet-xyz/tm@v0.34.24/rpc/jsonrpc/client/http_uri_client.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"strings"
     9  
    10  	types "github.com/vipernet-xyz/tm/rpc/jsonrpc/types"
    11  )
    12  
    13  const (
    14  	// URIClientRequestID in a request ID used by URIClient
    15  	URIClientRequestID = types.JSONRPCIntID(-1)
    16  )
    17  
    18  // URIClient is a JSON-RPC client, which sends POST form HTTP requests to the
    19  // remote server.
    20  //
    21  // URIClient is safe for concurrent use by multiple goroutines.
    22  type URIClient struct {
    23  	address string
    24  	client  *http.Client
    25  }
    26  
    27  var _ HTTPClient = (*URIClient)(nil)
    28  
    29  // NewURI returns a new client.
    30  // An error is returned on invalid remote.
    31  // The function panics when remote is nil.
    32  func NewURI(remote string) (*URIClient, error) {
    33  	parsedURL, err := newParsedURL(remote)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	httpClient, err := DefaultHTTPClient(remote)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	parsedURL.SetDefaultSchemeHTTP()
    44  
    45  	uriClient := &URIClient{
    46  		address: parsedURL.GetTrimmedURL(),
    47  		client:  httpClient,
    48  	}
    49  
    50  	return uriClient, nil
    51  }
    52  
    53  // Call issues a POST form HTTP request.
    54  func (c *URIClient) Call(ctx context.Context, method string,
    55  	params map[string]interface{}, result interface{},
    56  ) (interface{}, error) {
    57  	values, err := argsToURLValues(params)
    58  	if err != nil {
    59  		return nil, fmt.Errorf("failed to encode params: %w", err)
    60  	}
    61  
    62  	req, err := http.NewRequestWithContext(
    63  		ctx,
    64  		http.MethodPost,
    65  		c.address+"/"+method,
    66  		strings.NewReader(values.Encode()),
    67  	)
    68  	if err != nil {
    69  		return nil, fmt.Errorf("new request: %w", err)
    70  	}
    71  	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    72  
    73  	resp, err := c.client.Do(req)
    74  	if err != nil {
    75  		return nil, fmt.Errorf("post: %w", err)
    76  	}
    77  	defer resp.Body.Close()
    78  
    79  	responseBytes, err := io.ReadAll(resp.Body)
    80  	if err != nil {
    81  		return nil, fmt.Errorf("read response body: %w", err)
    82  	}
    83  
    84  	return unmarshalResponseBytes(responseBytes, URIClientRequestID, result)
    85  }