github.com/turingchain2020/turingchain@v1.1.21/rpc/jsonclient/jsonclient.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package jsonclient 实现JSON rpc客户端请求功能 6 package jsonclient 7 8 import ( 9 "bytes" 10 "crypto/tls" 11 "encoding/json" 12 "fmt" 13 "io/ioutil" 14 "net/http" 15 "strings" 16 17 "github.com/turingchain2020/turingchain/types" 18 "github.com/golang/protobuf/proto" 19 ) 20 21 // JSONClient a object of jsonclient 22 type JSONClient struct { 23 url string 24 prefix string 25 tlsVerify bool 26 client *http.Client 27 } 28 29 func addPrefix(prefix, name string) string { 30 if strings.Contains(name, ".") { 31 return name 32 } 33 return prefix + "." + name 34 } 35 36 // NewJSONClient produce a json object 37 func NewJSONClient(url string) (*JSONClient, error) { 38 return New("Turingchain", url, false) 39 } 40 41 // New produce a jsonclient by perfix and url 42 func New(prefix, url string, tlsVerify bool) (*JSONClient, error) { 43 httpcli := http.DefaultClient 44 if strings.Contains(url, "https") { //暂不校验tls证书 45 /* #nosec */ 46 httpcli = &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: !tlsVerify}}} 47 } 48 return &JSONClient{ 49 url: url, 50 prefix: prefix, 51 tlsVerify: tlsVerify, 52 client: httpcli, 53 }, nil 54 } 55 56 type clientRequest struct { 57 Method string `json:"method"` 58 Params [1]interface{} `json:"params"` 59 ID uint64 `json:"id"` 60 } 61 62 type clientResponse struct { 63 ID uint64 `json:"id"` 64 Result *json.RawMessage `json:"result"` 65 Error interface{} `json:"error"` 66 } 67 68 // Call jsonclinet call method 69 func (client *JSONClient) Call(method string, params, resp interface{}) error { 70 method = addPrefix(client.prefix, method) 71 req := &clientRequest{} 72 req.Method = method 73 req.Params[0] = params 74 data, err := json.Marshal(req) 75 if err != nil { 76 return err 77 } 78 //println("request JsonStr", string(data), "") 79 postresp, err := client.client.Post(client.url, "application/json", bytes.NewBuffer(data)) 80 if err != nil { 81 return err 82 } 83 defer postresp.Body.Close() 84 b, err := ioutil.ReadAll(postresp.Body) 85 if err != nil { 86 return err 87 } 88 //println("response", string(b), "") 89 cresp := &clientResponse{} 90 err = json.Unmarshal(b, &cresp) 91 if err != nil { 92 return err 93 } 94 if cresp.Error != nil /*|| cresp.Result == nil*/ { 95 x, ok := cresp.Error.(string) 96 if !ok { 97 return fmt.Errorf("invalid error %v", cresp.Error) 98 } 99 if x == "" { 100 x = "unspecified error" 101 } 102 return fmt.Errorf(x) 103 } 104 if cresp.Result == nil { 105 return types.ErrEmpty 106 } 107 if msg, ok := resp.(proto.Message); ok { 108 var str json.RawMessage 109 err = json.Unmarshal(*cresp.Result, &str) 110 if err != nil { 111 return err 112 } 113 b, err := str.MarshalJSON() 114 if err != nil { 115 return err 116 } 117 return types.JSONToPB(b, msg) 118 } 119 return json.Unmarshal(*cresp.Result, resp) 120 }