OSDN Git Service

extract api from blockchain (#478)
[bytom/bytom.git] / util / util.go
1 package util
2
3 import (
4         "context"
5         "net"
6         "net/http"
7         "path/filepath"
8         "strings"
9         "time"
10
11         "github.com/bytom/api"
12         "github.com/bytom/blockchain"
13         "github.com/bytom/blockchain/rpc"
14         "github.com/bytom/env"
15         jww "github.com/spf13/jwalterweatherman"
16 )
17
18 const (
19         // Success indicates the rpc calling is successful.
20         Success = iota
21         // ErrLocalExe indicates error occurs before the rpc calling.
22         ErrLocalExe
23         // ErrConnect indicates error occurs connecting to the bytomd, e.g.,
24         // bytomd can't parse the received arguments.
25         ErrConnect
26         // ErrLocalParse indicates error occurs locally when parsing the response.
27         ErrLocalParse
28         // ErrRemote indicates error occurs in bytomd.
29         ErrRemote
30 )
31
32 var (
33         home    = blockchain.HomeDirFromEnvironment()
34         coreURL = env.String("BYTOM_URL", "http://localhost:9888")
35 )
36
37 // Wraper rpc's client
38 func MustRPCClient() *rpc.Client {
39         // TODO(kr): refactor some of this cert-loading logic into bytom/blockchain
40         // and use it from cored as well.
41         // Note that this function, unlike maybeUseTLS in cored,
42         // does not load the cert and key from env vars,
43         // only from the filesystem.
44         certFile := filepath.Join(home, "tls.crt")
45         keyFile := filepath.Join(home, "tls.key")
46         config, err := blockchain.TLSConfig(certFile, keyFile, "")
47         if err == blockchain.ErrNoTLS {
48                 return &rpc.Client{BaseURL: *coreURL}
49         } else if err != nil {
50                 jww.ERROR.Println("loading TLS cert:", err)
51         }
52
53         t := &http.Transport{
54                 DialContext: (&net.Dialer{
55                         Timeout:   30 * time.Second,
56                         KeepAlive: 30 * time.Second,
57                         DualStack: true,
58                 }).DialContext,
59                 MaxIdleConns:          100,
60                 IdleConnTimeout:       90 * time.Second,
61                 TLSClientConfig:       config,
62                 TLSHandshakeTimeout:   10 * time.Second,
63                 ExpectContinueTimeout: 1 * time.Second,
64         }
65
66         url := *coreURL
67         if strings.HasPrefix(url, "http:") {
68                 url = "https:" + url[5:]
69         }
70
71         return &rpc.Client{
72                 BaseURL: url,
73                 Client:  &http.Client{Transport: t},
74         }
75 }
76
77 // Wrapper rpc call api.
78 func ClientCall(path string, req ...interface{}) (interface{}, int) {
79
80         var response = &api.Response{}
81         var request interface{}
82
83         if req != nil {
84                 request = req[0]
85         }
86
87         client := MustRPCClient()
88         client.Call(context.Background(), path, request, response)
89
90         switch response.Status {
91         case api.FAIL:
92                 jww.ERROR.Println(response.Msg)
93                 return nil, ErrRemote
94         case "":
95                 jww.ERROR.Println("Unable to connect to the bytomd")
96                 return nil, ErrConnect
97         }
98
99         return response.Data, Success
100 }