github.com/okex/exchain@v1.8.0/libs/tendermint/rpc/jsonrpc/client/cm39_http_json_client.go (about)

     1  package client
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io/ioutil"
     7  	"net/http"
     8  
     9  	"github.com/okex/exchain/libs/cosmos-sdk/codec"
    10  	"github.com/okex/exchain/libs/cosmos-sdk/types/errors"
    11  	coretypes "github.com/okex/exchain/libs/tendermint/rpc/core/types"
    12  	"github.com/okex/exchain/libs/tendermint/rpc/jsonrpc/types"
    13  )
    14  
    15  type decoder interface {
    16  	decode(cdc *codec.Codec, id types.JSONRPCIntID, data []byte, result interface{}) (interface{}, error)
    17  }
    18  
    19  type Cm39HttpJSONClientAdapter struct {
    20  	decoders map[string]decoder
    21  	*Client
    22  }
    23  
    24  func NewCm39HttpJSONClient(remote string, client *http.Client) (*Cm39HttpJSONClientAdapter, error) {
    25  	p, err := NewWithHTTPClient(remote, client)
    26  	if nil != err {
    27  		return nil, err
    28  	}
    29  	ret := &Cm39HttpJSONClientAdapter{Client: p}
    30  	ret.seal()
    31  	return ret, nil
    32  }
    33  
    34  var (
    35  	_ decoder = (*defaultFuncDecoder)(nil)
    36  )
    37  
    38  type defaultFuncDecoder struct {
    39  	secondChance      func() interface{}
    40  	convSecondToFirst func(s interface{}, f interface{})
    41  }
    42  
    43  func newDefaultFuncDecoder(secondChance func() interface{}, convSecondToFirst func(s interface{}, f interface{})) *defaultFuncDecoder {
    44  	return &defaultFuncDecoder{secondChance: secondChance, convSecondToFirst: convSecondToFirst}
    45  }
    46  
    47  func (d defaultFuncDecoder) decode(cdc *codec.Codec, id types.JSONRPCIntID, data []byte, result interface{}) (ret interface{}, err error) {
    48  	ret, err = unmarshalResponseBytes(cdc, data, id, result)
    49  	if nil == err {
    50  		return
    51  	}
    52  	another := d.secondChance()
    53  	ret2, err2 := unmarshalResponseBytes(cdc, data, id, another)
    54  	if nil != err2 {
    55  		err = errors.Wrap(err, "second error:"+err2.Error())
    56  		return
    57  	}
    58  	d.convSecondToFirst(ret2, result)
    59  	ret = result
    60  	err = nil
    61  	return
    62  }
    63  
    64  func (c *Cm39HttpJSONClientAdapter) seal() {
    65  	c.decoders = make(map[string]decoder)
    66  	c.decoders["tx"] = newDefaultFuncDecoder(func() interface{} {
    67  		return new(CM39ResultTx)
    68  	}, func(s interface{}, f interface{}) {
    69  		cm39 := s.(*CM39ResultTx)
    70  		cm4 := f.(*coretypes.ResultTx)
    71  		ConvTCM392CM4(cm39, cm4)
    72  	})
    73  	c.decoders["abci_query"] = newDefaultFuncDecoder(func() interface{} {
    74  		return new(CM39ResultABCIQuery)
    75  	}, func(s interface{}, f interface{}) {
    76  		cm39 := s.(*CM39ResultABCIQuery)
    77  		cm4 := f.(*coretypes.ResultABCIQuery)
    78  		ConvTCM39ResultABCIQuery2CM4(cm39, cm4)
    79  	})
    80  	c.decoders["broadcast_tx_commit"] = newDefaultFuncDecoder(func() interface{} {
    81  		return new(CM39ResultBroadcastTxCommit)
    82  	}, func(s interface{}, f interface{}) {
    83  		cm39 := s.(*CM39ResultBroadcastTxCommit)
    84  		cm4 := f.(*coretypes.ResultBroadcastTxCommit)
    85  		ConvTCM39BroadcastCommitTx2CM4(cm39, cm4)
    86  	})
    87  	c.decoders["block"] = newDefaultFuncDecoder(func() interface{} {
    88  		return new(coretypes.CM40ResultBlock)
    89  	}, func(s interface{}, f interface{}) {
    90  		cm4 := s.(*coretypes.CM40ResultBlock)
    91  		cm39 := f.(*coretypes.ResultBlock)
    92  		ret := cm4.ToCM39ResultBlock()
    93  		cm39.BlockID = ret.BlockID
    94  		cm39.Block = ret.Block
    95  	})
    96  }
    97  
    98  func (c *Cm39HttpJSONClientAdapter) Call(method string, params map[string]interface{}, result interface{}) (ret interface{}, err error) {
    99  	return c.call(method, params, result, c.decoders[method])
   100  }
   101  
   102  func (c *Cm39HttpJSONClientAdapter) call(method string, params map[string]interface{}, result interface{}, dec decoder) (interface{}, error) {
   103  	id := c.nextRequestID()
   104  
   105  	request, err := types.MapToRequest(c.cdc, id, method, params)
   106  	if err != nil {
   107  		return nil, errors.Wrap(err, "failed to encode params")
   108  	}
   109  
   110  	requestBytes, err := json.Marshal(request)
   111  	if err != nil {
   112  		return nil, errors.Wrap(err, "failed to marshal request")
   113  	}
   114  
   115  	requestBuf := bytes.NewBuffer(requestBytes)
   116  	httpRequest, err := http.NewRequest(http.MethodPost, c.address, requestBuf)
   117  	if err != nil {
   118  		return nil, errors.Wrap(err, "Request failed")
   119  	}
   120  	httpRequest.Header.Set("Content-Type", "text/json")
   121  	if c.username != "" || c.password != "" {
   122  		httpRequest.SetBasicAuth(c.username, c.password)
   123  	}
   124  	httpResponse, err := c.client.Do(httpRequest)
   125  	if err != nil {
   126  		return nil, errors.Wrap(err, "Post failed")
   127  	}
   128  	defer httpResponse.Body.Close() // nolint: errcheck
   129  
   130  	responseBytes, err := ioutil.ReadAll(httpResponse.Body)
   131  	if err != nil {
   132  		return nil, errors.Wrap(err, "failed to read response body")
   133  	}
   134  
   135  	if dec != nil {
   136  		return dec.decode(c.cdc, id, responseBytes, result)
   137  	}
   138  	return unmarshalResponseBytes(c.cdc, responseBytes, id, result)
   139  }