forked from ggwhite/go-hessian
-
Notifications
You must be signed in to change notification settings - Fork 0
/
proxy.go
142 lines (116 loc) · 2.72 KB
/
proxy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package hessian
import (
"errors"
"fmt"
"log"
"net/http"
"reflect"
)
type version int
// Versions
const (
V1 version = iota
V2
)
// ProxyConfig config for NewProxy
type ProxyConfig struct {
Version version
URL string
TypeMap map[string]reflect.Type
Client *http.Client
}
// Validate Proxy Config
func (c *ProxyConfig) Validate() error {
if len(c.URL) == 0 {
return fmt.Errorf("Proxy Config: URL is required")
}
if c.TypeMap == nil {
c.TypeMap = make(map[string]reflect.Type)
}
if c.Client == nil {
c.Client = &http.Client{}
}
return nil
}
// Proxy hessian proxy
type Proxy struct {
conf *ProxyConfig
client *http.Client
serializer Serializer
deserializer Deserializer
}
// Invoke input method name and arguments, it will send request to server, and parse response to interface
func (c *Proxy) Invoke(m string, args ...interface{}) (_ []interface{}, err error) {
c.serializer.Flush()
if err := c.serializer.Call(m, args...); err != nil {
return nil, err
}
req, err := http.NewRequest(http.MethodPost, c.conf.URL, c.serializer.Reader())
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "x-application/hessian")
req.Header.Set("Accept-Encoding", "deflate")
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.Println("status error", resp.StatusCode)
}
c.deserializer.Reset(resp.Body)
// Set the default error return value
err = errors.New("deserialize failed")
defer func() {
// Recover on read issues
_ = recover()
}()
ans, err := c.deserializer.Read()
if err != nil {
return nil, err
}
return ans, nil
}
// RegisterType input a type with Package field, register type mapping
func (c *Proxy) RegisterType(t reflect.Type) error {
var tmp reflect.Type
var pkg string
if t.Kind() == reflect.Ptr {
tmp = t.Elem()
} else {
tmp = t
}
for i, l := 0, tmp.NumField(); i < l; i++ {
if tmp.Field(i).Type == reflect.TypeOf(Package("")) {
pkg = tmp.Field(i).Tag.Get(tagName)
break
}
}
if len(pkg) == 0 {
return fmt.Errorf("input type is without Package field")
}
c.conf.TypeMap[pkg] = t
c.serializer.SetTypeMap(c.conf.TypeMap)
c.deserializer.SetTypeMap(c.conf.TypeMap)
return nil
}
// NewProxy create a proxy of the hessian service
func NewProxy(c *ProxyConfig) (*Proxy, error) {
if err := c.Validate(); err != nil {
return nil, err
}
switch c.Version {
default:
return nil, fmt.Errorf("Please set proxy version is V1 or V2")
case V1:
return &Proxy{
conf: c,
client: c.Client,
serializer: NewSerializerV1(),
deserializer: NewDeserializerV1(),
}, nil
case V2:
return nil, fmt.Errorf("Hessian V2.0 is unsupported")
}
}