github.com/go-kivik/kivik/v4@v4.3.2/x/server/bind.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 2 // use this file except in compliance with the License. You may obtain a copy of 3 // the License at 4 // 5 // http://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 // License for the specific language governing permissions and limitations under 11 // the License. 12 13 //go:build !js 14 15 package server 16 17 import ( 18 "encoding/json" 19 "mime" 20 "net/http" 21 22 internal "github.com/go-kivik/kivik/v4/int/errors" 23 ) 24 25 // bind binds the request to v if it is of type application/json or 26 // application/x-www-form-urlencoded. 27 func (s *Server) bind(r *http.Request, v interface{}) error { 28 defer r.Body.Close() 29 switch r.Method { 30 case http.MethodPatch, http.MethodPost, http.MethodPut: 31 // continue 32 default: 33 // simple query parsing 34 return s.bindForm(r, v) 35 } 36 ct, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) 37 switch ct { 38 case "application/json": 39 if err := json.NewDecoder(r.Body).Decode(v); err != nil { 40 return &internal.Error{Status: http.StatusBadRequest, Err: err} 41 } 42 return nil 43 case "application/x-www-form-urlencoded": 44 return s.bindForm(r, v) 45 default: 46 return &couchError{status: http.StatusUnsupportedMediaType, Err: "bad_content_type", Reason: "Content-Type must be 'application/x-www-form-urlencoded' or 'application/json'"} 47 } 48 } 49 50 func (s *Server) bindForm(r *http.Request, v interface{}) error { 51 defer r.Body.Close() 52 if err := r.ParseForm(); err != nil { 53 return &internal.Error{Status: http.StatusBadRequest, Err: err} 54 } 55 if err := s.formDecoder.Decode(r.Form, v); err != nil { 56 return &internal.Error{Status: http.StatusBadRequest, Err: err} 57 } 58 return nil 59 } 60 61 // bindJSON works like bind, but for endpoints that require application/json. 62 func (s *Server) bindJSON(r *http.Request, v interface{}) error { 63 defer r.Body.Close() 64 ct, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) 65 switch ct { 66 case "application/json": 67 return json.NewDecoder(r.Body).Decode(v) 68 default: 69 return &couchError{status: http.StatusUnsupportedMediaType, Err: "bad_content_type", Reason: "Content-Type must be 'application/json'"} 70 } 71 }