/
template.go
141 lines (129 loc) · 3.31 KB
/
template.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
package main
import (
"bytes"
"strings"
"text/template"
)
var httpTemplate = `
{{$svrType := .ServiceType}}
{{$svrName := .ServiceName}}
type {{.ServiceType}}HTTPServer interface {
{{- range .MethodSets}}
{{.Name}}(*gin.Context, *{{.Request}}) (*{{.Reply}}, error)
{{- end}}
}
func Register{{.ServiceType}}HTTPServer(r gin.IRoutes, srv {{.ServiceType}}HTTPServer) {
{{- range .Methods}}
r.{{.Method}}("{{.Path}}", _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler(srv))
{{- end}}
}
{{range .Methods}}
func _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler(srv {{$svrType}}HTTPServer) func(c *gin.Context) {
return func(c *gin.Context) {
var in {{.Request}}
{{- if .HasBody}}
if err := c.Bind(&in); err != nil {
c.AbortWithStatusJSON(400, err.Error())
return
}
{{- if not (eq .Body "")}}
if err := c.BindQuery(&in); err != nil {
return err
}
{{- end}}
{{- else}}
if err := c.BindQuery(&in{{.Body}}); err != nil {
return err
}
{{- end}}
{{- if .HasVars}}
if err := c.BindVars(&in); err != nil {
return err
}
{{- end}}
out, err := srv.{{.Name}}(c, &in)
if err != nil {
var e *httprpc.ResponseError
if errors.As(err, &e) {
c.JSON(e.Code, e.Msg)
c.Error(err)
return
}
var ae *httprpc.AbortError
if errors.As(err, &ae) {
c.AbortWithStatusJSON(ae.Code, ae.Msg)
return
}
} else {
c.Render(200, httprpc.Response{out})
}
}
}
{{end}}
type {{.ServiceType}}HTTPClient interface {
{{- range .MethodSets}}
{{.Name}}(ctx context.Context, req *{{.Request}}, opts ...http.CallOption) (rsp *{{.Reply}}, err error)
{{- end}}
}
type {{.ServiceType}}HTTPClientImpl struct{
cc *http.Client
}
func New{{.ServiceType}}HTTPClient (client *http.Client) {{.ServiceType}}HTTPClient {
return &{{.ServiceType}}HTTPClientImpl{client}
}
{{range .MethodSets}}
func (c *{{$svrType}}HTTPClientImpl) {{.Name}}(ctx context.Context, in *{{.Request}}, opts ...http.CallOption) (*{{.Reply}}, error) {
var out {{.Reply}}
pattern := "{{.Path}}"
path := binding.EncodeURL(pattern, in, {{not .HasBody}})
opts = append(opts, http.Operation("/{{$svrName}}/{{.OriginalName}}"))
opts = append(opts, http.PathTemplate(pattern))
{{if .HasBody -}}
err := c.cc.Invoke(ctx, "{{.Method}}", path, in{{.Body}}, &out{{.ResponseBody}}, opts...)
{{else -}}
err := c.cc.Invoke(ctx, "{{.Method}}", path, nil, &out{{.ResponseBody}}, opts...)
{{end -}}
if err != nil {
return nil, err
}
return &out, err
}
{{end}}
`
type serviceDesc struct {
ServiceType string // Greeter
ServiceName string // helloworld.Greeter
Metadata string // api/helloworld/helloworld.proto
Methods []*methodDesc
MethodSets map[string]*methodDesc
}
type methodDesc struct {
// method
Name string
OriginalName string // The parsed original name
Num int
Request string
Reply string
// http_rule
Path string
Method string
HasVars bool
HasBody bool
Body string
ResponseBody string
}
func (s *serviceDesc) execute() string {
s.MethodSets = make(map[string]*methodDesc)
for _, m := range s.Methods {
s.MethodSets[m.Name] = m
}
buf := new(bytes.Buffer)
tmpl, err := template.New("http").Parse(strings.TrimSpace(httpTemplate))
if err != nil {
panic(err)
}
if err := tmpl.Execute(buf, s); err != nil {
panic(err)
}
return strings.Trim(buf.String(), "\r\n")
}