// Parse parses the input commandline string (cmd, flags, and args). // returns the corresponding command Request object. func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *cmds.Command, []string, error) { path, opts, stringVals, cmd, err := parseOpts(input, root) if err != nil { return nil, nil, path, err } optDefs, err := root.GetOptions(path) if err != nil { return nil, cmd, path, err } req, err := cmds.NewRequest(path, opts, nil, nil, cmd, optDefs) if err != nil { return nil, cmd, path, err } // if -r is provided, and it is associated with the package builtin // recursive path option, allow recursive file paths recursiveOpt := req.Option(cmds.RecShort) recursive := false if recursiveOpt != nil && recursiveOpt.Definition() == cmds.OptionRecursivePath { recursive, _, err = recursiveOpt.Bool() if err != nil { return req, nil, nil, util.ErrCast() } } stringArgs, fileArgs, err := parseArgs(stringVals, stdin, cmd.Arguments, recursive, root) if err != nil { return req, cmd, path, err } req.SetArguments(stringArgs) file := files.NewSliceFile("", "", fileArgs) req.SetFiles(file) err = cmd.CheckArguments(req) if err != nil { return req, cmd, path, err } return req, cmd, path, nil }
// Parse parses the data in a http.Request and returns a command Request object func Parse(r *http.Request, root *cmds.Command) (cmds.Request, error) { if !strings.HasPrefix(r.URL.Path, ApiPath) { return nil, errors.New("Unexpected path prefix") } path := strings.Split(strings.TrimPrefix(r.URL.Path, ApiPath+"/"), "/") stringArgs := make([]string, 0) cmd, err := root.Get(path[:len(path)-1]) if err != nil { // 404 if there is no command at that path return nil, ErrNotFound } else if sub := cmd.Subcommand(path[len(path)-1]); sub == nil { if len(path) <= 1 { return nil, ErrNotFound } // if the last string in the path isn't a subcommand, use it as an argument // e.g. /objects/Qabc12345 (we are passing "Qabc12345" to the "objects" command) stringArgs = append(stringArgs, path[len(path)-1]) path = path[:len(path)-1] } else { cmd = sub } opts, stringArgs2 := parseOptions(r) stringArgs = append(stringArgs, stringArgs2...) // count required argument definitions numRequired := 0 for _, argDef := range cmd.Arguments { if argDef.Required { numRequired++ } } // count the number of provided argument values valCount := len(stringArgs) args := make([]string, valCount) valIndex := 0 requiredFile := "" for _, argDef := range cmd.Arguments { // skip optional argument definitions if there aren't sufficient remaining values if valCount-valIndex <= numRequired && !argDef.Required { continue } else if argDef.Required { numRequired-- } if argDef.Type == cmds.ArgString { if argDef.Variadic { for _, s := range stringArgs { args[valIndex] = s valIndex++ } valCount -= len(stringArgs) } else if len(stringArgs) > 0 { args[valIndex] = stringArgs[0] stringArgs = stringArgs[1:] valIndex++ } else { break } } else if argDef.Type == cmds.ArgFile && argDef.Required && len(requiredFile) == 0 { requiredFile = argDef.Name } } optDefs, err := root.GetOptions(path) if err != nil { return nil, err } // create cmds.File from multipart/form-data contents contentType := r.Header.Get(contentTypeHeader) mediatype, _, _ := mime.ParseMediaType(contentType) var f *files.MultipartFile if mediatype == "multipart/form-data" { f = &files.MultipartFile{Mediatype: mediatype} f.Reader, err = r.MultipartReader() if err != nil { return nil, err } } // if there is a required filearg, error if no files were provided if len(requiredFile) > 0 && f == nil { return nil, fmt.Errorf("File argument '%s' is required", requiredFile) } req, err := cmds.NewRequest(path, opts, args, f, cmd, optDefs) if err != nil { return nil, err } err = cmd.CheckArguments(req) if err != nil { return nil, err } return req, nil }