1
1
//
2
2
// DISCLAIMER
3
3
//
4
- // Copyright 2020 ArangoDB GmbH, Cologne, Germany
4
+ // Copyright 2020-2021 ArangoDB GmbH, Cologne, Germany
5
5
//
6
6
// Licensed under the Apache License, Version 2.0 (the "License");
7
7
// you may not use this file except in compliance with the License.
18
18
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19
19
//
20
20
// Author Adam Janikowski
21
+ // Author Tomasz Mielech
21
22
//
22
23
23
24
package connection
@@ -102,22 +103,21 @@ func (j *httpConnection) SetAuthentication(a Authentication) error {
102
103
return nil
103
104
}
104
105
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
120
117
}
118
+
119
+ // Return the default decoder.
120
+ return getJsonDecoder ()
121
121
}
122
122
123
123
func (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,
184
184
return nil , err
185
185
}
186
186
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 )
189
189
190
+ if output != nil {
191
+ // The output should be stored in the output variable.
190
192
if err = j .Decoder (resp .Content ()).Decode (body , output ); err != nil {
191
193
if err != io .EOF {
192
194
return nil , errors .WithStack (err )
193
195
}
194
196
}
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 )
198
197
}
199
198
200
199
return resp , nil
@@ -222,6 +221,7 @@ func (j httpConnection) do(ctx context.Context, req *httpRequest) (*httpResponse
222
221
ctx = context .Background ()
223
222
}
224
223
224
+ var bodyReader io.Reader
225
225
if req .Method () == http .MethodPost || req .Method () == http .MethodPut || req .Method () == http .MethodPatch {
226
226
decoder := j .Decoder (j .contentType )
227
227
if ! j .streamSender {
@@ -230,12 +230,7 @@ func (j httpConnection) do(ctx context.Context, req *httpRequest) (*httpResponse
230
230
return nil , nil , err
231
231
}
232
232
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
239
234
} else {
240
235
reader , writer := io .Pipe ()
241
236
go func () {
@@ -245,21 +240,16 @@ func (j httpConnection) do(ctx context.Context, req *httpRequest) (*httpResponse
245
240
}
246
241
}()
247
242
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
254
244
}
255
- } else {
256
- r , err := req .asRequest (ctx , nil )
257
- if err != nil {
258
- return nil , nil , errors .WithStack (err )
259
- }
260
- httpReq = r
261
245
}
262
246
247
+ r , err := req .asRequest (ctx , bodyReader )
248
+ if err != nil {
249
+ return nil , nil , errors .WithStack (err )
250
+ }
251
+ httpReq = r
252
+
263
253
resp , err := j .client .Do (httpReq )
264
254
if err != nil {
265
255
log .Debugf ("(%s) Request failed: %s" , id , err .Error ())
@@ -276,3 +266,18 @@ func (j httpConnection) do(ctx context.Context, req *httpRequest) (*httpResponse
276
266
277
267
return & httpResponse {response : resp , request : req }, nil , nil
278
268
}
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