mirror of
https://github.com/ggicci/httpin.git
synced 2024-11-24 08:32:45 +02:00
88 lines
2.1 KiB
Go
88 lines
2.1 KiB
Go
|
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
|
||
|
}
|