Skip to content

Commit

Permalink
refactor: stricter type checking in http query parser
Browse files Browse the repository at this point in the history
  • Loading branch information
aschmahmann committed Dec 2, 2020
1 parent 11d59a2 commit 9549a8c
Showing 1 changed file with 27 additions and 31 deletions.
58 changes: 27 additions & 31 deletions http/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,33 +60,45 @@ func parseRequest(r *http.Request, root *cmds.Command) (*cmds.Request, error) {
return nil, ErrNotFound
}

opts, stringArgs2 := parseOptions(r)
iopts := make(map[string]interface{}, len(opts))
opts := make(map[string]interface{})
optDefs, err := root.GetOptions(pth)
if err != nil {
return nil, err
}
for k, v := range opts {
iopts[k] = v
if optDef, ok := optDefs[k]; ok {
name := optDef.Names()[0]
if k != name {
iopts[name] = v
delete(iopts, k)

query := r.URL.Query()
// Note: len(v) is guaranteed by the above function to always be greater than 0
for k, v := range query {
if k == "arg" {
stringArgs = append(stringArgs, v...)
} else {
optDef, ok := optDefs[k]
if !ok {
opts[k] = v[0]
continue
}

if optDef.Type() != cmds.Strings && len(v) > 0 {
iopts[name] = v[0]
name := optDef.Names()[0]
opts[name] = v

switch optType := optDef.Type(); optType {
case cmds.Strings:
opts[name] = v
case cmds.Bool, cmds.Int, cmds.Int64, cmds.Uint, cmds.Uint64, cmds.Float, cmds.String:
if len(v) > 1 {
return nil, fmt.Errorf("expected key %s to have only a single value, received %v", name, v)
}
opts[name] = v[0]
default:
return nil, fmt.Errorf("unsupported option type. key: %s, type: %v", k, optType)
}
}
}
// default to setting encoding to JSON
if _, ok := iopts[cmds.EncLong]; !ok {
iopts[cmds.EncLong] = cmds.JSON
if _, ok := opts[cmds.EncLong]; !ok {
opts[cmds.EncLong] = cmds.JSON
}

stringArgs = append(stringArgs, stringArgs2...)

// count required argument definitions
numRequired := 0
for _, argDef := range cmd.Arguments {
Expand Down Expand Up @@ -168,22 +180,6 @@ func parseRequest(r *http.Request, root *cmds.Command) (*cmds.Request, error) {
return req, err
}

func parseOptions(r *http.Request) (map[string][]string, []string) {
opts := make(map[string][]string)
var args []string

query := r.URL.Query()
for k, v := range query {
if k == "arg" {
args = v
} else {
opts[k] = v
}
}

return opts, args
}

// parseResponse decodes a http.Response to create a cmds.Response
func parseResponse(httpRes *http.Response, req *cmds.Request) (cmds.Response, error) {
res := &Response{
Expand Down

0 comments on commit 9549a8c

Please sign in to comment.