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 {
32 case v == "null" || v == "":
34 case strings.HasPrefix(v, "["):
36 err := json.Unmarshal([]byte(v), &j)
41 case strings.HasPrefix(v, "{"):
42 var j map[string]interface{}
43 err := json.Unmarshal([]byte(v), &j)
48 case strings.HasPrefix(v, "\""):
50 err := json.Unmarshal([]byte(v), &j)
55 case k == "limit" || k == "offset":
56 params[k], err = strconv.ParseInt(v, 10, 64)
63 // TODO: Need to accept "?foo[]=bar&foo[]=baz"
64 // as foo=["bar","baz"]?
67 if ct, _, err := mime.ParseMediaType(req.Header.Get("Content-Type")); err != nil && ct == "application/json" {
68 jsonParams := map[string]interface{}{}
69 err := json.NewDecoder(req.Body).Decode(jsonParams)
71 return nil, httpError(http.StatusBadRequest, err)
73 for k, v := range jsonParams {
76 if attrsKey != "" && params[attrsKey] == nil {
77 // Copy top-level parameters from JSON request
78 // body into params[attrsKey]. Some SDKs rely
79 // on this Rails API feature; see
80 // https://api.rubyonrails.org/v5.2.1/classes/ActionController/ParamsWrapper.html
81 params[attrsKey] = jsonParams
85 routeParams, _ := req.Context().Value(httprouter.ParamsKey).(httprouter.Params)
86 for _, p := range routeParams {
87 params[p.Key] = p.Value
90 if v, ok := params[attrsKey]; ok && attrsKey != "" {
92 delete(params, attrsKey)
97 // Copy src to dst, using json as an intermediate format in order to
98 // invoke src's json-marshaling and dst's json-unmarshaling behaviors.
99 func (rtr *router) transcode(src interface{}, dst interface{}) error {
104 errw = json.NewEncoder(pw).Encode(src)
107 err := json.NewDecoder(pr).Decode(dst)