mirror of
https://github.com/ggicci/httpin.git
synced 2024-11-28 08:49:05 +02:00
67 lines
1.2 KiB
Go
67 lines
1.2 KiB
Go
package httpin
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"reflect"
|
|
)
|
|
|
|
type ContextKey int
|
|
|
|
const (
|
|
Input ContextKey = iota // the primary key to get the input object in the context injected by httpin
|
|
|
|
FieldSet
|
|
)
|
|
|
|
type core struct {
|
|
inputType reflect.Type
|
|
tree *FieldResolver
|
|
errorStatusCode int
|
|
}
|
|
|
|
func New(inputStruct interface{}, opts ...option) (*core, error) {
|
|
typ := reflect.TypeOf(inputStruct) // retrieve type information
|
|
if typ.Kind() == reflect.Ptr {
|
|
typ = typ.Elem()
|
|
}
|
|
if typ.Kind() != reflect.Struct {
|
|
return nil, UnsupportedTypeError{Type: typ}
|
|
}
|
|
|
|
engine := &core{
|
|
inputType: typ,
|
|
errorStatusCode: 422,
|
|
}
|
|
for _, opt := range opts {
|
|
opt(engine)
|
|
}
|
|
|
|
if err := engine.build(); err != nil {
|
|
return nil, fmt.Errorf("httpin: %w", err)
|
|
}
|
|
|
|
return engine, nil
|
|
}
|
|
|
|
func (e *core) Decode(req *http.Request) (interface{}, error) {
|
|
if err := req.ParseForm(); err != nil {
|
|
return nil, err
|
|
}
|
|
rv, err := e.tree.resolve(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("httpin: %w", err)
|
|
}
|
|
return rv.Interface(), nil
|
|
}
|
|
|
|
// build builds extractors for the exported fields of the input struct.
|
|
func (e *core) build() error {
|
|
tree, err := buildResolverTree(e.inputType)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
e.tree = tree
|
|
return nil
|
|
}
|