1
0
mirror of https://github.com/ggicci/httpin.git synced 2024-11-24 08:32:45 +02:00
httpin/form.go

88 lines
2.1 KiB
Go
Raw Normal View History

2021-05-07 13:02:34 +02:00
package httpin
import (
"fmt"
"net/http"
"reflect"
)
func FormValueExtractor(ctx *DirectiveContext) error {
return extractFromKVS(ctx, ctx.Request.Form, false)
}
func HeaderValueExtractor(ctx *DirectiveContext) error {
return extractFromKVS(ctx, ctx.Request.Header, true)
}
func extractFromKVSWithKeyForSlice(ctx *DirectiveContext, kvs map[string][]string, key string) error {
elemType := ctx.ValueType.Elem()
decoder := decoderOf(elemType)
if decoder == nil {
return UnsupportedTypeError{ctx.ValueType}
}
formValues, exists := kvs[key]
if !exists {
debug(" > key %q not found in %s\n", key, ctx.Executor)
return nil
}
theSlice := reflect.MakeSlice(ctx.ValueType, len(formValues), len(formValues))
for i, formValue := range formValues {
if err := decoder.Decode([]byte(formValue), theSlice.Index(i)); err != nil {
return fmt.Errorf("at index %d: %w", i, err)
}
}
ctx.Value.Elem().Set(theSlice)
ctx.DeliverContextValue(fieldSet, true)
return nil
}
func extractFromKVSWithKey(ctx *DirectiveContext, kvs map[string][]string, key string) error {
if ctx.Context.Value(fieldSet) == true {
debug(" > field already set, skip\n")
return nil
}
// NOTE(ggicci): Array?
if ctx.ValueType.Kind() == reflect.Slice {
return extractFromKVSWithKeyForSlice(ctx, kvs, key)
}
decoder := decoderOf(ctx.ValueType)
if decoder == nil {
return UnsupportedTypeError{ctx.ValueType}
}
formValues, exists := kvs[key]
if !exists {
debug(" > key %q not found in %s\n", key, ctx.Executor)
return nil
}
var got string
if len(formValues) > 0 {
got = formValues[0]
}
if err := decoder.Decode([]byte(got), ctx.Value.Elem()); err != nil {
return err
}
ctx.DeliverContextValue(fieldSet, true)
return nil
}
func extractFromKVS(ctx *DirectiveContext, kvs map[string][]string, headerKey bool) error {
for _, key := range ctx.Directive.Argv {
debug(" > execute directive %q with key %q\n", ctx.Directive.Executor, key)
if headerKey {
key = http.CanonicalHeaderKey(key)
}
if err := extractFromKVSWithKey(ctx, kvs, key); err != nil {
return err
}
}
return nil
}