mirror of
https://github.com/ggicci/httpin.git
synced 2024-11-24 08:32:45 +02:00
96 lines
2.4 KiB
Go
96 lines
2.4 KiB
Go
package httpin
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"reflect"
|
|
)
|
|
|
|
// formValueExtractor implements the "form" executor who extracts values from
|
|
// the forms of an HTTP request.
|
|
func formValueExtractor(ctx *DirectiveContext) error {
|
|
return extractFromKVS(ctx, ctx.Request.Form, false)
|
|
}
|
|
|
|
// headerValueExtractor implements the "header" executor who extracts values
|
|
// from the HTTP headers.
|
|
func headerValueExtractor(ctx *DirectiveContext) error {
|
|
return extractFromKVS(ctx, ctx.Request.Header, true)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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 interfaceValue, err := decoder.Decode([]byte(got)); err != nil {
|
|
return err
|
|
} else {
|
|
ctx.Value.Elem().Set(reflect.ValueOf(interfaceValue))
|
|
}
|
|
|
|
ctx.DeliverContextValue(FieldSet, true)
|
|
return nil
|
|
}
|
|
|
|
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 interfaceValue, err := decoder.Decode([]byte(formValue)); err != nil {
|
|
return fmt.Errorf("at index %d: %w", i, err)
|
|
} else {
|
|
theSlice.Index(i).Set(reflect.ValueOf(interfaceValue))
|
|
}
|
|
}
|
|
|
|
ctx.Value.Elem().Set(theSlice)
|
|
ctx.DeliverContextValue(FieldSet, true)
|
|
return nil
|
|
}
|