Skip to content

Commit

Permalink
convert resp complete
Browse files Browse the repository at this point in the history
  • Loading branch information
bughou committed Jul 10, 2020
1 parent c12ff66 commit c95d3bd
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 55 deletions.
12 changes: 6 additions & 6 deletions convert-req.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ func getReqFieldsConvertFuncs(typ reflect.Type, path string) (funcs []convertFun
funcs = append(funcs, newParamConvertFunc(f.Type, f.Index, path))
case "Query":
funcs = append(funcs, newQueryConvertFunc(f.Type, f.Index))
case "Header":
funcs = append(funcs, newHeaderConvertFunc(f.Type, f.Index))
case "Body":
funcs = append(funcs, newBodyConvertFunc(f.Type, f.Index))
case "Header":
funcs = append(funcs, newHeaderConvertFunc(f.Type, f.Index))
case "Session":
funcs = append(funcs, newSessionConvertFunc(f.Type, f.Index))
case "Ctx":
Expand All @@ -71,16 +71,16 @@ func newParamConvertFunc(typ reflect.Type, index []int, path string) convertFunc
}

func newQueryConvertFunc(typ reflect.Type, index []int) convertFunc {
converters.ValidateQueryOrHeader(typ, `Query`)
converters.ValidateQuery(typ)
return func(req reflect.Value, ctx *Context) error {
return converters.ConvertQueryOrHeader(req.FieldByIndex(index), ctx.Request.URL.Query())
return converters.ConvertQuery(req.FieldByIndex(index), ctx.Request.URL.Query())
}
}

func newHeaderConvertFunc(typ reflect.Type, index []int) convertFunc {
converters.ValidateQueryOrHeader(typ, `Header`)
converters.ValidateHeader(typ)
return func(req reflect.Value, ctx *Context) error {
return converters.ConvertQueryOrHeader(req.FieldByIndex(index), ctx.Request.Header)
return converters.ConvertHeader(req.FieldByIndex(index), ctx.Request.Header)
}
}

Expand Down
38 changes: 37 additions & 1 deletion convert-resp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package goa
import (
"log"
"reflect"

"github.com/lovego/goa/converters"
)

var errorType = reflect.TypeOf((*error)(nil)).Elem()

func newRespWriteFunc(typ reflect.Type) (reflect.Type, func(*Context, reflect.Value)) {
if typ.Kind() != reflect.Ptr {
log.Panic("resp parameter of handler func must be a struct pointer.")
Expand All @@ -13,5 +17,37 @@ func newRespWriteFunc(typ reflect.Type) (reflect.Type, func(*Context, reflect.Va
if typ.Kind() != reflect.Struct {
log.Panic("resp parameter of handler func must be a struct pointer.")
}
return typ, nil

for i := 0; i < typ.NumField(); i++ {
f := typ.Field(i)
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":
converters.ValidateRespHeader(typ)
default:
log.Panicf("Unknow field: resp.%s.", f.Name)
}
}
return typ, func(ctx *Context, resp reflect.Value) {
var data interface{}
var err error

for i := 0; i < typ.NumField(); i++ {
f := typ.Field(i)
switch f.Name {
case "Data":
data = resp.FieldByIndex(f.Index).Interface()
case "Error":
err = resp.FieldByIndex(f.Index).Interface().(error)
case "Header":
converters.WriteRespHeader(resp.FieldByIndex(f.Index), ctx.ResponseWriter.Header())
}
}
ctx.Data(data, err)
}
}
28 changes: 12 additions & 16 deletions convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,39 +42,35 @@ func convertHandler(h interface{}, path string) HandlerFunc {

// handler example
func handlerExample(req *struct {
Title string
Desc string
Params struct {
Title string
Desc string
Param struct {
Id int64
}
Query struct {
Id int64
Page int64
}
Headers struct {
Cookie string
}
Body struct {
Id int64
Name string
}
Header struct {
Cookie string
}
Session struct {
UserId int64
}
Ctx *Context
}, resp *struct {
Error error
Headers struct {
SetCookie string
}
Body struct {
Id int64
Name string
} `当XXX时的返回体格式`
Body2 struct {
Data struct {
Id int64
Name string
} `当YYY时的返回体格式`
}
Error error
Header struct {
SetCookie string
}
}) {
// resp.Body, resp.Error = users.Get(req.Params.Id)
}
65 changes: 65 additions & 0 deletions converters/header.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package converters

import (
"log"
"net/http"
"reflect"

"github.com/lovego/struct_tag"
"github.com/lovego/structs"
)

func ValidateHeader(typ reflect.Type) {
if typ.Kind() != reflect.Struct {
log.Panic("req.Header must be a struct.")
}
structs.Traverse(reflect.New(typ).Elem(), true, func(_ reflect.Value, f reflect.StructField) bool {
if !isSupportedType(f.Type) {
log.Panicf("req.Header.%s: type must be string, number or bool.", f.Name)
}
return false
})
return
}

func ConvertHeader(value reflect.Value, map2strs map[string][]string) (err error) {
structs.Traverse(value, true, func(v reflect.Value, f reflect.StructField) bool {
key, _ := struct_tag.Lookup(string(f.Tag), "header")
if key == "" {
key = f.Name
}
values := map2strs[key]
if len(values) > 0 && values[0] != "" {
err = Set(v, values[0])
}
return err != nil // if err != nil, stop Traverse
})
return
}

func ValidateRespHeader(typ reflect.Type) {
if typ.Kind() != reflect.Struct {
log.Panic("resp.Header must be a struct.")
}
structs.Traverse(reflect.New(typ).Elem(), false, func(_ reflect.Value, f reflect.StructField) bool {
if f.Type.Kind() != reflect.String {
log.Panicf("req.Header.%s: type must be string.", f.Name)
}
return false
})
return
}

func WriteRespHeader(value reflect.Value, header http.Header) {
structs.Traverse(value, false, func(v reflect.Value, f reflect.StructField) bool {
if value := v.String(); value != "" {
key, _ := struct_tag.Lookup(string(f.Tag), "header")
if key == "" {
key = f.Name
}
header.Set(key, value)
}
return false
})
return
}
32 changes: 32 additions & 0 deletions converters/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package converters

import (
"log"
"reflect"

"github.com/lovego/structs"
)

func ValidateQuery(typ reflect.Type) {
if typ.Kind() != reflect.Struct {
log.Panic("req.Query must be a struct.")
}
structs.Traverse(reflect.New(typ).Elem(), true, func(_ reflect.Value, f reflect.StructField) bool {
if !isSupportedType(f.Type) {
log.Panicf("req.Query.%s: type must be string, number or bool.", f.Name)
}
return false
})
return
}

func ConvertQuery(value reflect.Value, map2strs map[string][]string) (err error) {
structs.Traverse(value, true, func(v reflect.Value, f reflect.StructField) bool {
values := map2strs[lowercaseFirstLetter(f.Name)]
if len(values) > 0 && values[0] != "" {
err = Set(v, values[0])
}
return err != nil // if err != nil, stop Traverse
})
return
}
32 changes: 0 additions & 32 deletions converters/query_or_header.go

This file was deleted.

0 comments on commit c95d3bd

Please sign in to comment.