11//
22// DISCLAIMER
33//
4- // Copyright 2020 ArangoDB GmbH, Cologne, Germany
4+ // Copyright 2020-2021 ArangoDB GmbH, Cologne, Germany
55//
66// Licensed under the Apache License, Version 2.0 (the "License");
77// you may not use this file except in compliance with the License.
1818// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919//
2020// Author Adam Janikowski
21+ // Author Tomasz Mielech
2122//
2223
2324package connection
@@ -102,22 +103,21 @@ func (j *httpConnection) SetAuthentication(a Authentication) error {
102103 return nil
103104}
104105
105- func (j httpConnection ) Decoder (content string ) Decoder {
106- switch content {
107- case ApplicationVPack :
108- return getVPackDecoder ()
109- case ApplicationJSON :
110- return getJsonDecoder ()
111- default :
112- switch j .contentType {
113- case ApplicationVPack :
114- return getVPackDecoder ()
115- case ApplicationJSON :
116- return getJsonDecoder ()
117- default :
118- return getJsonDecoder ()
119- }
106+ // Decoder returns the decoder according to the response content type or HTTP connection request content type.
107+ // If the content type is unknown then it returns default JSON decoder.
108+ func (j httpConnection ) Decoder (contentType string ) Decoder {
109+ // First try to get decoder by the content type of the response.
110+ if decoder := getDecoderByContentType (contentType ); decoder != nil {
111+ return decoder
112+ }
113+
114+ // Next try to get decoder by the content type of the HTTP connection.
115+ if decoder := getDecoderByContentType (j .contentType ); decoder != nil {
116+ return decoder
120117 }
118+
119+ // Return the default decoder.
120+ return getJsonDecoder ()
121121}
122122
123123func (j httpConnection ) DoWithReader (ctx context.Context , request Request ) (Response , io.ReadCloser , error ) {
@@ -184,17 +184,16 @@ func (j httpConnection) doWithOutput(ctx context.Context, request *httpRequest,
184184 return nil , err
185185 }
186186
187- if output != nil {
188- defer dropBodyData (body ) // In case if there is data drop it all
187+ // The body should be closed at the end of the function.
188+ defer dropBodyData (body )
189189
190+ if output != nil {
191+ // The output should be stored in the output variable.
190192 if err = j .Decoder (resp .Content ()).Decode (body , output ); err != nil {
191193 if err != io .EOF {
192194 return nil , errors .WithStack (err )
193195 }
194196 }
195- } else {
196- // We still need to read data from request, but we can do this in background and ignore output
197- defer dropBodyData (body )
198197 }
199198
200199 return resp , nil
@@ -222,6 +221,7 @@ func (j httpConnection) do(ctx context.Context, req *httpRequest) (*httpResponse
222221 ctx = context .Background ()
223222 }
224223
224+ var bodyReader io.Reader
225225 if req .Method () == http .MethodPost || req .Method () == http .MethodPut || req .Method () == http .MethodPatch {
226226 decoder := j .Decoder (j .contentType )
227227 if ! j .streamSender {
@@ -230,12 +230,7 @@ func (j httpConnection) do(ctx context.Context, req *httpRequest) (*httpResponse
230230 return nil , nil , err
231231 }
232232
233- r , err := req .asRequest (ctx , b )
234- if err != nil {
235- return nil , nil , errors .WithStack (err )
236- }
237-
238- httpReq = r
233+ bodyReader = b
239234 } else {
240235 reader , writer := io .Pipe ()
241236 go func () {
@@ -245,21 +240,16 @@ func (j httpConnection) do(ctx context.Context, req *httpRequest) (*httpResponse
245240 }
246241 }()
247242
248- r , err := req .asRequest (ctx , reader )
249- if err != nil {
250- return nil , nil , errors .WithStack (err )
251- }
252-
253- httpReq = r
243+ bodyReader = reader
254244 }
255- } else {
256- r , err := req .asRequest (ctx , nil )
257- if err != nil {
258- return nil , nil , errors .WithStack (err )
259- }
260- httpReq = r
261245 }
262246
247+ r , err := req .asRequest (ctx , bodyReader )
248+ if err != nil {
249+ return nil , nil , errors .WithStack (err )
250+ }
251+ httpReq = r
252+
263253 resp , err := j .client .Do (httpReq )
264254 if err != nil {
265255 log .Debugf ("(%s) Request failed: %s" , id , err .Error ())
@@ -276,3 +266,18 @@ func (j httpConnection) do(ctx context.Context, req *httpRequest) (*httpResponse
276266
277267 return & httpResponse {response : resp , request : req }, nil , nil
278268}
269+
270+ // getDecoderByContentType returns the decoder according to the content type.
271+ // If content type is unknown then nil is returned.
272+ func getDecoderByContentType (contentType string ) Decoder {
273+ switch contentType {
274+ case ApplicationVPack :
275+ return getVPackDecoder ()
276+ case ApplicationJSON :
277+ return getJsonDecoder ()
278+ case PlainText , ApplicationOctetStream , ApplicationZip :
279+ return getBytesDecoder ()
280+ default :
281+ return nil
282+ }
283+ }
0 commit comments