diff options
Diffstat (limited to 'pkg/api/handlers/decoder.go')
-rw-r--r-- | pkg/api/handlers/decoder.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/pkg/api/handlers/decoder.go b/pkg/api/handlers/decoder.go new file mode 100644 index 000000000..890d77ecc --- /dev/null +++ b/pkg/api/handlers/decoder.go @@ -0,0 +1,91 @@ +package handlers + +import ( + "encoding/json" + "reflect" + "time" + + "github.com/gorilla/schema" + "github.com/sirupsen/logrus" +) + +// NewAPIDecoder returns a configured schema.Decoder +func NewAPIDecoder() *schema.Decoder { + _ = ParseDateTime + + d := schema.NewDecoder() + d.IgnoreUnknownKeys(true) + d.RegisterConverter(map[string][]string{}, convertUrlValuesString) + d.RegisterConverter(time.Time{}, convertTimeString) + return d +} + +// On client: +// v := map[string][]string{ +// "dangling": {"true"}, +// } +// +// payload, err := jsoniter.MarshalToString(v) +// if err != nil { +// panic(err) +// } +// payload = url.QueryEscape(payload) +func convertUrlValuesString(query string) reflect.Value { + f := map[string][]string{} + + err := json.Unmarshal([]byte(query), &f) + if err != nil { + logrus.Infof("convertUrlValuesString: Failed to Unmarshal %s: %s", query, err.Error()) + } + + return reflect.ValueOf(f) +} + +// isZero() can be used to determine if parsing failed. +func convertTimeString(query string) reflect.Value { + var ( + err error + t time.Time + ) + + for _, f := range []string{ + time.UnixDate, + time.ANSIC, + time.RFC1123, + time.RFC1123Z, + time.RFC3339, + time.RFC3339Nano, + time.RFC822, + time.RFC822Z, + time.RFC850, + time.RubyDate, + time.Stamp, + time.StampMicro, + time.StampMilli, + time.StampNano, + } { + t, err = time.Parse(f, query) + if err == nil { + return reflect.ValueOf(t) + } + + if _, isParseError := err.(*time.ParseError); isParseError { + // Try next format + continue + } else { + break + } + } + + // We've exhausted all formats, or something bad happened + if err != nil { + logrus.Infof("convertTimeString: Failed to parse %s: %s", query, err.Error()) + } + return reflect.ValueOf(time.Time{}) +} + +// ParseDateTime is a helper function to aid in parsing different Time/Date formats +// isZero() can be used to determine if parsing failed. +func ParseDateTime(query string) time.Time { + return convertTimeString(query).Interface().(time.Time) +} |