/
response.go
183 lines (163 loc) · 4.61 KB
/
response.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package biu
import (
"fmt"
"net/http"
"sync"
"github.com/emicklei/go-restful"
"github.com/json-iterator/go"
)
var codeDesc struct {
sync.Once
m map[int]string
}
func init() {
codeDesc.Do(func() {
codeDesc.m = make(map[int]string)
})
}
// Handle transform a biu handler to a restful.RouteFunction.
func Handle(f func(ctx Ctx)) restful.RouteFunction {
return func(request *restful.Request, response *restful.Response) {
f(Ctx{
Request: request,
Response: response,
})
}
}
// Filter transform a biu handler to a restful.FilterFunction
func Filter(f func(ctx Ctx)) restful.FilterFunction {
return func(request *restful.Request, response *restful.Response,
chain *restful.FilterChain) {
f(Ctx{
Request: request,
Response: response,
FilterChain: chain,
})
}
}
// WrapHandler wraps a biu handler to http.HandlerFunc
func WrapHandler(f func(ctx Ctx)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
f(Ctx{
Request: restful.NewRequest(r),
Response: restful.NewResponse(w),
})
}
}
// AddErrDesc adds map of code-message to stdCodeDesc
func AddErrDesc(m map[int]string) {
for k, v := range m {
codeDesc.m[k] = v
}
}
// Ctx wrap *restful.Request and *restful.Response in one struct.
type Ctx struct {
*restful.Request
*restful.Response
*restful.FilterChain
}
// ResponseJSON is a convenience method
// for writing a value wrap in CommonResp as JSON.
// It uses jsoniter for marshalling the value.
func (ctx *Ctx) ResponseJSON(v interface{}) {
CommonResponse(ctx.Response, 0, "", v)
}
// ResponseError is a convenience method to response an error code and message.
// It uses jsoniter for marshalling the value.
func (ctx *Ctx) ResponseError(msg string, code int) {
CommonResponse(ctx.Response, code, msg, nil)
}
// ContainsError is a convenience method to check error is nil.
// If error is nil, it will return false,
// else it will log the error, make a CommonResp response and return true.
// if code is 0, it will use err.Error() as CommonResp.message.
func (ctx *Ctx) ContainsError(err error, code int, v ...interface{}) bool {
msg := codeDesc.m[code]
if len(v) > 0 {
msg = fmt.Sprintf(msg, v...)
}
if CheckError(err, Log().Int("code", code).Str("msg", msg)) {
return false
}
if code == 0 {
msg = err.Error()
}
ResponseError(ctx.Response, msg, code)
return true
}
// ResponseStdErrCode is a convenience method response a code
// with msg in Code Desc.
func (ctx *Ctx) ResponseStdErrCode(code int, v ...interface{}) {
msg := codeDesc.m[code]
if len(v) > 0 {
msg = fmt.Sprintf(msg, v...)
}
ResponseError(ctx.Response, msg, code)
}
// UserID returns UserID stored in attribute.
func (ctx *Ctx) UserID() string {
userID, ok := ctx.Attribute("UserID").(string)
if !ok {
return ""
}
return userID
}
// ResponseJSON is a convenience method
// for writing a value wrap in CommonResp as JSON.
// It uses jsoniter for marshalling the value.
func ResponseJSON(w http.ResponseWriter, v interface{}) {
CommonResponse(w, 0, "", v)
}
// ResponseError is a convenience method to response an error code and message.
// It uses jsoniter for marshalling the value.
func ResponseError(w http.ResponseWriter, msg string, code int) {
CommonResponse(w, code, msg, nil)
}
// ContainsError is a convenience method to check error is nil.
// If error is nil, it will return false,
// else it will log the error, make a CommonResp response and return true.
// if code is 0, it will use err.Error() as CommonResp.message.
func ContainsError(w http.ResponseWriter, err error, code int) bool {
msg := codeDesc.m[code]
if CheckError(err, Log().Int("code", code).Str("msg", msg)) {
return false
}
if code == 0 {
msg = err.Error()
}
ResponseError(w, msg, code)
return true
}
// CheckError is a convenience method to check error is nil.
// If error is nil, it will return true,
// else it will log the error and return false
func CheckError(err error, log *LogEvt) bool {
if err == nil {
return true
}
if log != nil {
Info("verify error", log.Err(err))
}
return false
}
// CommonResponse is a response func.
// just replace it if you'd like to custom response.
var CommonResponse = func(w http.ResponseWriter,
code int, message string, data interface{}) {
if err := writeJSON(w, http.StatusOK, CommonResp{
Code: code,
Message: message,
Data: data,
}); err != nil {
Warn("json encode", Log().Err(err))
}
}
func writeJSON(resp http.ResponseWriter, status int, v interface{}) error {
if v == nil {
resp.WriteHeader(status)
return nil
}
resp.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
resp.WriteHeader(status)
return jsoniter.NewEncoder(resp).Encode(v)
}