@@ -27,25 +27,25 @@ func (cli *Client) get(ctx context.Context, path string, query url.Values, heade
2727 return cli .sendRequest (ctx , http .MethodGet , path , query , nil , headers )
2828}
2929
30- // post sends an http request to the docker API using the method POST with a specific Go context .
31- func (cli * Client ) post (ctx context.Context , path string , query url.Values , obj interface {}, headers http.Header ) (* http.Response , error ) {
32- body , headers , err := encodeBody ( obj , headers )
30+ // post sends an http POST request to the API.
31+ func (cli * Client ) post (ctx context.Context , path string , query url.Values , body interface {}, headers http.Header ) (* http.Response , error ) {
32+ jsonBody , headers , err := prepareJSONRequest ( body , headers )
3333 if err != nil {
3434 return nil , err
3535 }
36- return cli .sendRequest (ctx , http .MethodPost , path , query , body , headers )
36+ return cli .sendRequest (ctx , http .MethodPost , path , query , jsonBody , headers )
3737}
3838
3939func (cli * Client ) postRaw (ctx context.Context , path string , query url.Values , body io.Reader , headers http.Header ) (* http.Response , error ) {
4040 return cli .sendRequest (ctx , http .MethodPost , path , query , body , headers )
4141}
4242
43- func (cli * Client ) put (ctx context.Context , path string , query url.Values , obj interface {}, headers http.Header ) (* http.Response , error ) {
44- body , headers , err := encodeBody ( obj , headers )
43+ func (cli * Client ) put (ctx context.Context , path string , query url.Values , body interface {}, headers http.Header ) (* http.Response , error ) {
44+ jsonBody , headers , err := prepareJSONRequest ( body , headers )
4545 if err != nil {
4646 return nil , err
4747 }
48- return cli .putRaw (ctx , path , query , body , headers )
48+ return cli .putRaw (ctx , path , query , jsonBody , headers )
4949}
5050
5151// putRaw sends an http request to the docker API using the method PUT.
@@ -64,26 +64,36 @@ func (cli *Client) delete(ctx context.Context, path string, query url.Values, he
6464 return cli .sendRequest (ctx , http .MethodDelete , path , query , nil , headers )
6565}
6666
67- func encodeBody (obj interface {}, headers http.Header ) (io.Reader , http.Header , error ) {
68- if obj == nil {
67+ // prepareJSONRequest encodes the given body to JSON and returns it as an [io.Reader], and sets the Content-Type
68+ // header. If body is nil, or a nil-interface, a "nil" body is returned without
69+ // error.
70+ //
71+ // TODO(thaJeztah): should this return an error if a different Content-Type is already set?
72+ // TODO(thaJeztah): is "nil" the appropriate approach for an empty body, or should we use [http.NoBody] (or similar)?
73+ func prepareJSONRequest (body interface {}, headers http.Header ) (io.Reader , http.Header , error ) {
74+ if body == nil {
6975 return nil , headers , nil
7076 }
7177 // encoding/json encodes a nil pointer as the JSON document `null`,
7278 // irrespective of whether the type implements json.Marshaler or encoding.TextMarshaler.
7379 // That is almost certainly not what the caller intended as the request body.
74- if reflect .TypeOf (obj ).Kind () == reflect .Ptr && reflect .ValueOf (obj ).IsNil () {
80+ //
81+ // TODO(thaJeztah): consider moving this to jsonEncode, which would also allow returning an (empty) reader instead of nil.
82+ if reflect .TypeOf (body ).Kind () == reflect .Ptr && reflect .ValueOf (body ).IsNil () {
7583 return nil , headers , nil
7684 }
7785
78- body , err := encodeData ( obj )
86+ jsonBody , err := jsonEncode ( body )
7987 if err != nil {
8088 return nil , headers , err
8189 }
82- if headers == nil {
83- headers = make (map [string ][]string )
90+ hdr := http.Header {}
91+ if headers != nil {
92+ hdr = headers .Clone ()
8493 }
85- headers ["Content-Type" ] = []string {"application/json" }
86- return body , headers , nil
94+
95+ hdr .Set ("Content-Type" , "application/json" )
96+ return jsonBody , hdr , nil
8797}
8898
8999func (cli * Client ) buildRequest (ctx context.Context , method , path string , body io.Reader , headers http.Header ) (* http.Request , error ) {
@@ -293,14 +303,14 @@ func (cli *Client) addHeaders(req *http.Request, headers http.Header) *http.Requ
293303 return req
294304}
295305
296- func encodeData (data interface {}) (* bytes. Buffer , error ) {
297- params := bytes .NewBuffer ( nil )
306+ func jsonEncode (data interface {}) (io. Reader , error ) {
307+ var params bytes.Buffer
298308 if data != nil {
299- if err := json .NewEncoder (params ).Encode (data ); err != nil {
309+ if err := json .NewEncoder (& params ).Encode (data ); err != nil {
300310 return nil , err
301311 }
302312 }
303- return params , nil
313+ return & params , nil
304314}
305315
306316func ensureReaderClosed (response * http.Response ) {
0 commit comments