/
http_controller.go
145 lines (129 loc) · 3.69 KB
/
http_controller.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
143
144
145
package ghttp
import (
"github.com/gosrv/gbase/controller"
"github.com/gosrv/gbase/gl"
"github.com/gosrv/gbase/gnet"
"reflect"
"strings"
)
const (
HttpController = "HttpController"
)
type IHttpController interface {
controller.IController
ViewRender() IViewRender
}
var IHttpControllerType = reflect.TypeOf((*IHttpController)(nil)).Elem()
type httpController struct {
group string
ctype string
finder controller.IControlPointFinder
trigger controller.IControlPointTrigger
viewRender IViewRender
}
func (this *httpController) Group() string {
return this.group
}
func (this *httpController) Type() string {
return this.ctype
}
func (this *httpController) Finder() controller.IControlPointFinder {
return this.finder
}
func (this *httpController) Trigger() controller.IControlPointTrigger {
return this.trigger
}
func (this *httpController) ViewRender() IViewRender {
return this.viewRender
}
func NewHttpRestController(group string) IHttpController {
return NewHttpController(group, NewRestViewRender())
}
func NewHttpController(group string, viewRender IViewRender) IHttpController {
return &httpController{
group: group,
ctype: HttpController,
finder: controller.FuncTypeControlPointFinder(httpControlPointFinder),
trigger: controller.FuncControlPointTrigger(httpControlPointTrigger),
viewRender: viewRender,
}
}
func httpControlPointFinder(bean controller.IController, group controller.IControlPointGroup) {
rval := reflect.ValueOf(bean)
rtype := reflect.TypeOf(bean)
if rval.Kind() != reflect.Ptr || rval.Elem().Kind() == reflect.Ptr {
panic("bean only support pointer to struct")
}
for i := 0; i < rval.NumMethod(); i++ {
method := rval.Method(i)
mtype := rtype.Method(i)
// 入参一个是ISessionCtx
if method.Type().NumIn() < 1 || method.Type().In(0) != gnet.ISessionCtxType {
continue
}
// 返回参数最多1个
if method.Type().NumOut() >= 2 {
continue
}
methodName := mtype.Name
key := "/"
for k, m := range methodName {
if m >= 'A' && m <= 'Z' && k != 0 {
key += "/" + strings.ToLower(string(m))
} else {
key += strings.ToLower(string(m))
}
}
if group.GetControlPoint(key) != nil {
gl.Panic("duplicate control point %v in %v and %v", key, reflect.TypeOf(bean),
reflect.TypeOf(group.GetControlPoint(key).Bean))
}
ctlPoint := &controller.ControlPoint{
Bean: bean,
Method: method,
ParamTypes: make([]reflect.Type, method.Type().NumIn(), method.Type().NumIn()),
ReturnTypes: make([]reflect.Type, method.Type().NumIn(), method.Type().NumIn()),
Controller: bean,
}
for j := 0; j < method.Type().NumIn(); j++ {
ctlPoint.ParamTypes[j] = method.Type().In(j)
}
for j := 0; j < method.Type().NumOut(); j++ {
ctlPoint.ReturnTypes[j] = method.Type().Out(j)
}
group.AddControlPoint(key, ctlPoint)
}
}
func httpControlPointTrigger(controlPoint *controller.ControlPoint, ctx gnet.ISessionCtx) interface{} {
params := make([]reflect.Value, len(controlPoint.ParamTypes), len(controlPoint.ParamTypes))
for i := 0; i < len(params); i++ {
val := ctx.GetByType(controlPoint.ParamTypes[i])
if val == nil {
nval := reflect.New(controlPoint.ParamTypes[i]).Elem()
params[i] = nval
for nval.Kind() == reflect.Ptr {
nval.Set(reflect.New(nval.Type().Elem()))
nval = nval.Elem()
}
// 注入数据
ParamInject(nval, ctx)
} else {
switch val.(type) {
case reflect.Value:
params[i] = val.(reflect.Value)
default:
params[i] = reflect.ValueOf(val)
}
}
}
reps := controlPoint.Method.Call(params)
switch len(reps) {
case 0:
return nil
case 1:
return reps[0].Interface()
default:
gl.Panic("invalid return num, expect 1")
}
return nil
}