X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/2aa5e89121d595426dc884e87807e8d7a53be858..4a919918a4ce37b5290793f02fa959db1c073590:/lib/controller/router/request.go diff --git a/lib/controller/router/request.go b/lib/controller/router/request.go index aa2cd636cf..377f7243c0 100644 --- a/lib/controller/router/request.go +++ b/lib/controller/router/request.go @@ -27,9 +27,32 @@ func (rtr *router) loadRequestParams(req *http.Request, attrsKey string) (map[st return nil, httpError(http.StatusBadRequest, err) } params := map[string]interface{}{} + + // Load parameters from req.Form, which (after + // req.ParseForm()) includes the query string and -- when + // Content-Type is application/x-www-form-urlencoded -- the + // request body. for k, values := range req.Form { + // All of these form values arrive as strings, so we + // need some type-guessing to accept non-string + // inputs: + // + // Values for parameters that take ints (limit=1) or + // bools (include_trash=1) are parsed accordingly. + // + // "null" and "" are nil. + // + // Values that look like JSON objects, arrays, or + // strings are parsed as JSON. + // + // The rest are left as strings. for _, v := range values { switch { + case intParams[k]: + params[k], err = strconv.ParseInt(v, 10, 64) + if err != nil { + return nil, err + } case boolParams[k]: params[k] = stringToBool(v) case v == "null" || v == "": @@ -55,11 +78,6 @@ func (rtr *router) loadRequestParams(req *http.Request, attrsKey string) (map[st return nil, err } params[k] = j - case k == "limit" || k == "offset": - params[k], err = strconv.ParseInt(v, 10, 64) - if err != nil { - return nil, err - } default: params[k] = v } @@ -100,6 +118,19 @@ func (rtr *router) loadRequestParams(req *http.Request, attrsKey string) (map[st params["attrs"] = v delete(params, attrsKey) } + + if order, ok := params["order"].(string); ok { + // We must accept strings ("foo, bar desc") and arrays + // (["foo", "bar desc"]) because RailsAPI does. + // Convert to an array here before trying to unmarshal + // into options structs. + if order == "" { + delete(params, "order") + } else { + params["order"] = strings.Split(order, ",") + } + } + return params, nil } @@ -120,7 +151,13 @@ func (rtr *router) transcode(src interface{}, dst interface{}) error { return err } +var intParams = map[string]bool{ + "limit": true, + "offset": true, +} + var boolParams = map[string]bool{ + "distinct": true, "ensure_unique_name": true, "include_trash": true, "include_old_versions": true,