Compare commits

...

2 Commits

Author SHA1 Message Date
Adrien Marquès 22947db2b6
fix: mark parameter as parsed after successful parsing
- avoid parsing multiple times in a row ; it has no side-effect but is useless
 - actually does not cause any issue, but for consistency sake!
2020-02-28 18:41:05 +01:00
Adrien Marquès 3e718c96e8
return error when parsing parameters 2020-02-28 17:50:55 +01:00
1 changed files with 42 additions and 15 deletions

View File

@ -4,8 +4,19 @@ import (
"encoding/json"
"fmt"
"reflect"
"git.xdrm.io/go/aicra/internal/cerr"
)
// ErrUnknownType is returned when encountering an unknown type
const ErrUnknownType = cerr.Error("unknown type")
// ErrInvalidJSON is returned when json parse failed
const ErrInvalidJSON = cerr.Error("invalid json")
// ErrInvalidRootType is returned when json is a map
const ErrInvalidRootType = cerr.Error("invalid json root type")
// Parameter represents an http request parameter
// that can be of type URL, GET, or FORM (multipart, json, urlencoded)
type Parameter struct {
@ -22,16 +33,23 @@ type Parameter struct {
}
// Parse parameter (json-like) if not already done
func (i *Parameter) Parse() {
func (i *Parameter) Parse() error {
/* (1) Stop if already parsed or nil*/
if i.Parsed || i.Value == nil {
return
return nil
}
/* (2) Try to parse value */
i.Value = parseParameter(i.Value)
parsed, err := parseParameter(i.Value)
if err != nil {
return err
}
i.Parsed = true
i.Value = parsed
return nil
}
// parseParameter parses http GET/POST data
@ -39,7 +57,7 @@ func (i *Parameter) Parse() {
// - size = 1 : return json of first element
// - size > 1 : return array of json elements
// - string : return json if valid, else return raw string
func parseParameter(data interface{}) interface{} {
func parseParameter(data interface{}) (interface{}, error) {
dtype := reflect.TypeOf(data)
dvalue := reflect.ValueOf(data)
@ -50,17 +68,21 @@ func parseParameter(data interface{}) interface{} {
// 1. Return nothing if empty
if dvalue.Len() == 0 {
return nil
return data, nil
}
// 2. only return first element if alone
if dvalue.Len() == 1 {
element := dvalue.Index(0)
if element.Kind() != reflect.String {
return nil
// try to parse if a string (containing json)
if element.Kind() == reflect.String {
return parseParameter(element.String())
}
return parseParameter(element.String())
// already typed
return data, nil
}
@ -72,12 +94,17 @@ func parseParameter(data interface{}) interface{} {
// ignore non-string
if element.Kind() != reflect.String {
result[i] = nil
continue
}
result[i] = parseParameter(element.String())
parsed, err := parseParameter(element.String())
if err != nil {
return data, err
}
result[i] = parsed
}
return result
return result, nil
/* (2) string -> parse */
case reflect.String:
@ -94,23 +121,23 @@ func parseParameter(data interface{}) interface{} {
mapval, ok := result.(map[string]interface{})
if !ok {
return dvalue.String()
return dvalue.String(), ErrInvalidRootType
}
wrapped, ok := mapval["wrapped"]
if !ok {
return dvalue.String()
return dvalue.String(), ErrInvalidJSON
}
return wrapped
return wrapped, nil
}
// else return as string
return dvalue.String()
return dvalue.String(), nil
}
/* (3) NIL if unknown type */
return dvalue
return dvalue, ErrUnknownType
}