Skip to content

Commit 19afc33

Browse files
committed
Support AppError and hijack filters
1 parent c747c2a commit 19afc33

File tree

1 file changed

+56
-19
lines changed

1 file changed

+56
-19
lines changed

http/http.go

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,30 +75,43 @@ func (v SystemComplexError) Error() string {
7575
return fmt.Sprintf("%v, %v", v.Code.Error(), v.Message)
7676
}
7777

78+
// application level, with code.
79+
type AppError interface {
80+
Code() int
81+
error
82+
}
83+
7884
// http standard error response.
7985
// @remark for not SystemError, we will use logger.E to print it.
8086
// @remark user can use WriteError() for simple api.
8187
func Error(ctx ol.Context, err error) http.Handler {
8288
// for complex error, use code instead.
8389
if v, ok := err.(SystemComplexError); ok {
8490
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
85-
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, err)
86-
jsonHandler(ctx, v).ServeHTTP(w, r)
91+
jsonHandler(ctx, FilterCplxSystemError(ctx, w, r, v)).ServeHTTP(w, r)
8792
})
8893
}
8994

9095
// for int error, use code instead.
9196
if v, ok := err.(SystemError); ok {
92-
return jsonHandler(ctx, map[string]int{"code": int(v)})
97+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
98+
jsonHandler(ctx, FilterSystemError(ctx, w, r, v)).ServeHTTP(w, r)
99+
})
93100
}
94101

102+
// for application error, use code instead.
103+
if v, ok := err.(AppError); ok {
104+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
105+
jsonHandler(ctx, FilterAppError(ctx, w, r, v)).ServeHTTP(w, r)
106+
})
107+
}
108+
109+
// unknown error, log and response detail
95110
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
96111
SetHeader(w)
97112
w.Header().Set("Content-Type", HttpJson)
98113

99-
// unknown error, log and response detail
100-
http.Error(w, err.Error(), http.StatusInternalServerError)
101-
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, err)
114+
http.Error(w, FilterError(ctx, w, r, err), http.StatusInternalServerError)
102115
})
103116
}
104117

@@ -112,19 +125,9 @@ func CplxError(ctx ol.Context, code SystemError, message string) http.Handler {
112125
// @remark user can use nil v to response success, which data is null.
113126
// @remark user can use WriteData() for simple api.
114127
func Data(ctx ol.Context, v interface{}) http.Handler {
115-
rv := map[string]interface{}{
116-
"code": 0,
117-
"server": os.Getpid(),
118-
"data": v,
119-
}
120-
121-
// for string, directly use it without convert,
122-
// for the type covert by golang maybe modify the content.
123-
if v, ok := v.(string); ok {
124-
rv["data"] = v
125-
}
126-
127-
return jsonHandler(ctx, rv)
128+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
129+
jsonHandler(ctx, FilterData(ctx, w, r, v)).ServeHTTP(w, r)
130+
})
128131
}
129132

130133
// set http header, for directly use the w,
@@ -211,3 +214,37 @@ func WriteError(ctx ol.Context, w http.ResponseWriter, r *http.Request, err erro
211214
func WriteCplxError(ctx ol.Context, w http.ResponseWriter, r *http.Request, code SystemError, message string) {
212215
CplxError(ctx, code, message).ServeHTTP(w, r)
213216
}
217+
218+
// for hijack to define the response structure.
219+
// user can redefine these functions for special response.
220+
var FilterCplxSystemError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, o SystemComplexError) interface{} {
221+
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, o)
222+
return o
223+
}
224+
var FilterSystemError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, o SystemError) interface{} {
225+
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, o)
226+
return map[string]int{"code": int(o)}
227+
}
228+
var FilterAppError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, err AppError) interface{} {
229+
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, err)
230+
return map[string]interface{}{"code": err.Code(), "data": err.Error()}
231+
}
232+
var FilterError = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, err error) string {
233+
ol.Ef(ctx, "Serve %v failed, err is %+v", r.URL, err)
234+
return err.Error()
235+
}
236+
var FilterData = func(ctx ol.Context, w http.ResponseWriter, r *http.Request, o interface{}) interface{} {
237+
rv := map[string]interface{}{
238+
"code": 0,
239+
"server": os.Getpid(),
240+
"data": o,
241+
}
242+
243+
// for string, directly use it without convert,
244+
// for the type covert by golang maybe modify the content.
245+
if v, ok := o.(string); ok {
246+
rv["data"] = v
247+
}
248+
249+
return rv
250+
}

0 commit comments

Comments
 (0)