-
Notifications
You must be signed in to change notification settings - Fork 1
/
convert-resp.go
66 lines (59 loc) · 1.45 KB
/
convert-resp.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
package goa
import (
"log"
"reflect"
"github.com/lovego/goa/convert"
)
var errorType = reflect.TypeOf((*error)(nil)).Elem()
func newRespWriteFunc(typ reflect.Type, hasCtx bool) (reflect.Type, func(*Context, reflect.Value)) {
if typ.Kind() != reflect.Ptr {
log.Panic("resp parameter of handler func must be a struct pointer.")
}
typ = typ.Elem()
if typ.Kind() != reflect.Struct {
log.Panic("resp parameter of handler func must be a struct pointer.")
}
if validateRespFields(typ) {
return typ, nil
}
return typ, func(ctx *Context, resp reflect.Value) {
if hasCtx && ctx.ResponseBodySize() > 0 {
return
}
var data interface{}
var err error
convert.Traverse(resp, false, func(v reflect.Value, f reflect.StructField) bool {
switch f.Name {
case "Error":
if e := v.Interface(); e != nil {
err = e.(error)
}
case "Data":
data = v.Interface()
case "Header":
convert.WriteRespHeader(v, ctx.ResponseWriter.Header())
}
return true
})
ctx.Data(data, err)
}
}
func validateRespFields(typ reflect.Type) bool {
empty := true
convert.TraverseType(typ, func(f reflect.StructField) {
switch f.Name {
case "Data":
// data can be of any type
case "Error":
if !f.Type.Implements(errorType) {
log.Panicf(`resp.Error must be of "error" type.`)
}
case "Header":
convert.ValidateRespHeader(f.Type)
default:
log.Panicf("Unknown field: resp.%s.", f.Name)
}
empty = false
})
return empty
}