1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
15 "github.com/julienschmidt/httprouter"
18 // Parse req as an Arvados V1 API request and return the request
21 // If the request has a parameter whose name is attrsKey (e.g.,
22 // "collection"), it is renamed to "attrs".
23 func (rtr *router) loadRequestParams(req *http.Request, attrsKey string) (map[string]interface{}, error) {
24 err := req.ParseForm()
26 return nil, httpError(http.StatusBadRequest, err)
28 params := map[string]interface{}{}
29 for k, values := range req.Form {
30 for _, v := range values {
33 params[k] = stringToBool(v)
34 case v == "null" || v == "":
36 case strings.HasPrefix(v, "["):
38 err := json.Unmarshal([]byte(v), &j)
43 case strings.HasPrefix(v, "{"):
44 var j map[string]interface{}
45 err := json.Unmarshal([]byte(v), &j)
50 case strings.HasPrefix(v, "\""):
52 err := json.Unmarshal([]byte(v), &j)
57 case k == "limit" || k == "offset":
58 params[k], err = strconv.ParseInt(v, 10, 64)
65 // TODO: Need to accept "?foo[]=bar&foo[]=baz"
66 // as foo=["bar","baz"]?
69 if ct, _, err := mime.ParseMediaType(req.Header.Get("Content-Type")); err != nil && ct == "application/json" {
70 jsonParams := map[string]interface{}{}
71 err := json.NewDecoder(req.Body).Decode(jsonParams)
73 return nil, httpError(http.StatusBadRequest, err)
75 for k, v := range jsonParams {
78 if attrsKey != "" && params[attrsKey] == nil {
79 // Copy top-level parameters from JSON request
80 // body into params[attrsKey]. Some SDKs rely
81 // on this Rails API feature; see
82 // https://api.rubyonrails.org/v5.2.1/classes/ActionController/ParamsWrapper.html
83 params[attrsKey] = jsonParams
87 routeParams, _ := req.Context().Value(httprouter.ParamsKey).(httprouter.Params)
88 for _, p := range routeParams {
89 params[p.Key] = p.Value
92 if v, ok := params[attrsKey]; ok && attrsKey != "" {
94 delete(params, attrsKey)
99 // Copy src to dst, using json as an intermediate format in order to
100 // invoke src's json-marshaling and dst's json-unmarshaling behaviors.
101 func (rtr *router) transcode(src interface{}, dst interface{}) error {
106 errw = json.NewEncoder(pw).Encode(src)
109 err := json.NewDecoder(pr).Decode(dst)
116 var boolParams = map[string]bool{
117 "ensure_unique_name": true,
118 "include_trash": true,
119 "include_old_versions": true,
122 func stringToBool(s string) bool {
124 case "", "false", "0":