2
2
// For a copy, see <https://opensource.org/licenses/MIT>.
3
3
4
4
using System . Net ;
5
+ using System . Net . Http ;
5
6
using System . Net . Http . Headers ;
6
7
using System . Net . Http . Json ;
8
+ using System . Text ;
7
9
using System . Text . Json ;
8
10
using System . Text . Json . Serialization ;
9
11
@@ -33,30 +35,23 @@ protected internal async Task<TrybeResponse> SendAsync(
33
35
CancellationToken cancellationToken = default )
34
36
{
35
37
Ensure . IsNotNull ( request , nameof ( request ) ) ;
36
- var httpReq = CreateHttpRequest ( request ) ;
38
+ using var httpReq = CreateHttpRequest ( request ) ;
37
39
HttpResponseMessage ? httpResp = null ;
38
40
39
41
try
40
42
{
41
43
httpResp = await _http . SendAsync ( httpReq , cancellationToken )
42
44
. ConfigureAwait ( false ) ;
43
45
44
- var transformedResponse = await TransformResponse (
46
+ var ( transformedResponse , capturedResponseContent ) = await TransformResponse (
45
47
httpReq . Method ,
46
48
httpReq . RequestUri ,
47
49
httpResp )
48
50
. ConfigureAwait ( false ) ;
49
51
50
- if ( _settings . CaptureRequestContent && httpReq . Content is not null )
51
- {
52
- transformedResponse . RequestContent = await httpReq . Content . ReadAsStringAsync ( )
53
- . ConfigureAwait ( false ) ;
54
- }
55
-
56
- if ( _settings . CaptureResponseContent && httpResp . Content is not null )
52
+ if ( _settings . CaptureResponseContent || ! httpResp . IsSuccessStatusCode )
57
53
{
58
- transformedResponse . ResponseContent = await httpResp . Content . ReadAsStringAsync ( )
59
- . ConfigureAwait ( false ) ; ;
54
+ transformedResponse . ResponseContent = capturedResponseContent ;
60
55
}
61
56
62
57
return transformedResponse ;
@@ -92,30 +87,28 @@ protected internal async Task<TrybeResponse> SendAsync<TRequest>(
92
87
where TRequest : notnull
93
88
{
94
89
Ensure . IsNotNull ( request , nameof ( request ) ) ;
95
- var httpReq = CreateHttpRequest ( request ) ;
90
+ var ( httpReq , capturedRequestContent ) = CreateHttpRequest ( request ) ;
96
91
HttpResponseMessage ? httpResp = null ;
97
92
98
93
try
99
94
{
100
95
httpResp = await _http . SendAsync ( httpReq , cancellationToken )
101
96
. ConfigureAwait ( false ) ;
102
97
103
- var transformedResponse = await TransformResponse (
98
+ var ( transformedResponse , capturedResponseContent ) = await TransformResponse (
104
99
httpReq . Method ,
105
100
httpReq . RequestUri ,
106
101
httpResp )
107
102
. ConfigureAwait ( false ) ; ;
108
103
109
- if ( _settings . CaptureRequestContent && httpReq . Content is not null )
104
+ if ( _settings . CaptureRequestContent )
110
105
{
111
- transformedResponse . RequestContent = await httpReq . Content . ReadAsStringAsync ( )
112
- . ConfigureAwait ( false ) ;
106
+ transformedResponse . RequestContent = capturedRequestContent ;
113
107
}
114
108
115
- if ( _settings . CaptureResponseContent && httpResp . Content is not null )
109
+ if ( _settings . CaptureResponseContent || ! httpResp . IsSuccessStatusCode )
116
110
{
117
- transformedResponse . ResponseContent = await httpResp . Content . ReadAsStringAsync ( )
118
- . ConfigureAwait ( false ) ;
111
+ transformedResponse . ResponseContent = capturedResponseContent ;
119
112
}
120
113
121
114
return transformedResponse ;
@@ -163,13 +156,7 @@ protected internal async Task<TrybeResponse<TResponse>> FetchAsync<TResponse>(
163
156
httpReq . Method ,
164
157
httpReq . RequestUri ,
165
158
httpResp )
166
- . ConfigureAwait ( false ) ; ;
167
-
168
- if ( ( _settings . CaptureRequestContent || ! httpResp . IsSuccessStatusCode ) && httpReq . Content is not null )
169
- {
170
- transformedResponse . RequestContent = await httpReq . Content . ReadAsStringAsync ( )
171
- . ConfigureAwait ( false ) ; ;
172
- }
159
+ . ConfigureAwait ( false ) ;
173
160
174
161
if ( _settings . CaptureResponseContent || ! httpResp . IsSuccessStatusCode )
175
162
{
@@ -201,6 +188,18 @@ protected internal async Task<TrybeResponse<TResponse>> FetchAsync<TResponse>(
201
188
202
189
return response ;
203
190
}
191
+ finally
192
+ {
193
+ if ( httpReq is not null )
194
+ {
195
+ httpReq . Dispose ( ) ;
196
+ }
197
+
198
+ if ( httpResp is not null )
199
+ {
200
+ httpResp . Dispose ( ) ;
201
+ }
202
+ }
204
203
}
205
204
206
205
protected internal async Task < TrybeResponse < TResponse > > FetchAsync < TRequest , TResponse > (
@@ -210,7 +209,7 @@ protected internal async Task<TrybeResponse<TResponse>> FetchAsync<TRequest, TRe
210
209
where TResponse : class
211
210
{
212
211
Ensure . IsNotNull ( request , nameof ( request ) ) ;
213
- var httpReq = CreateHttpRequest ( request ) ;
212
+ var ( httpReq , capturedRequestContent ) = CreateHttpRequest ( request ) ;
214
213
HttpResponseMessage ? httpResp = null ;
215
214
216
215
try
@@ -224,10 +223,9 @@ protected internal async Task<TrybeResponse<TResponse>> FetchAsync<TRequest, TRe
224
223
httpResp )
225
224
. ConfigureAwait ( false ) ; ;
226
225
227
- if ( ( _settings . CaptureRequestContent || ! httpResp . IsSuccessStatusCode ) && httpReq . Content is not null )
226
+ if ( _settings . CaptureRequestContent )
228
227
{
229
- transformedResponse . RequestContent = await httpReq . Content . ReadAsStringAsync ( )
230
- . ConfigureAwait ( false ) ; ;
228
+ transformedResponse . RequestContent = capturedRequestContent ;
231
229
}
232
230
233
231
if ( _settings . CaptureResponseContent || ! httpResp . IsSuccessStatusCode )
@@ -260,6 +258,18 @@ protected internal async Task<TrybeResponse<TResponse>> FetchAsync<TRequest, TRe
260
258
261
259
return response ;
262
260
}
261
+ finally
262
+ {
263
+ if ( httpReq is not null )
264
+ {
265
+ httpReq . Dispose ( ) ;
266
+ }
267
+
268
+ if ( httpResp is not null )
269
+ {
270
+ httpResp . Dispose ( ) ;
271
+ }
272
+ }
263
273
}
264
274
#endregion
265
275
@@ -281,33 +291,54 @@ protected internal HttpRequestMessage CreateHttpRequest(
281
291
return message ;
282
292
}
283
293
284
- protected internal HttpRequestMessage CreateHttpRequest < TRequest > (
294
+ protected internal ( HttpRequestMessage , string ? ) CreateHttpRequest < TRequest > (
285
295
TrybeRequest < TRequest > request )
286
296
where TRequest : notnull
287
297
{
288
298
var message = CreateHttpRequest ( ( TrybeRequest ) request ) ;
299
+ string ? capturedContent = null ;
289
300
290
- message . Content = JsonContent . Create (
291
- inputValue : request . Data , options : _serializerOptions ) ;
301
+ if ( _settings . CaptureRequestContent )
302
+ {
303
+ capturedContent = JsonSerializer . Serialize ( request . Data , _serializerOptions ) ;
304
+ message . Content = new StringContent ( capturedContent , Encoding . UTF8 , "application/json" ) ;
305
+ }
306
+ else
307
+ {
308
+ message . Content = JsonContent . Create (
309
+ inputValue : request . Data , options : _serializerOptions ) ;
310
+ }
292
311
293
- return message ;
312
+ return ( message , capturedContent ) ;
294
313
}
295
314
#endregion
296
315
297
316
#region Postprocessing
298
- protected internal async Task < TrybeResponse > TransformResponse (
317
+ protected internal async Task < ( TrybeResponse , string ? ) > TransformResponse (
299
318
HttpMethod method ,
300
319
Uri uri ,
301
320
HttpResponseMessage response ,
302
321
CancellationToken cancellationToken = default )
303
322
{
304
- async Task < Error > GetTrybeError ( )
323
+ var rateLimiting = GetRateLimiting ( response ) ;
324
+
325
+ if ( response . IsSuccessStatusCode )
326
+ {
327
+ return ( new TrybeResponse (
328
+ method ,
329
+ uri ,
330
+ response . IsSuccessStatusCode ,
331
+ response . StatusCode ,
332
+ rateLimiting : rateLimiting ) , null ) ;
333
+ }
334
+ else
305
335
{
306
336
Error error ;
307
- if ( response . Content is not null )
308
- {
309
- var result = await response . Content . ReadFromJsonAsync < ErrorContainer > ( cancellationToken )
337
+ string ? stringContent = await response . Content . ReadAsStringAsync ( )
310
338
. ConfigureAwait ( false ) ;
339
+ if ( stringContent is { Length : > 0 } )
340
+ {
341
+ var result = JsonSerializer . Deserialize < ErrorContainer > ( stringContent , _deserializerOptions ) ;
311
342
312
343
if ( result ? . Message is not { Length : > 0 } )
313
344
{
@@ -323,29 +354,14 @@ async Task<Error> GetTrybeError()
323
354
error = new Error ( Resources . ApiClient_NoErrorMessage ) ;
324
355
}
325
356
326
- return error ;
327
- }
328
-
329
- if ( response . IsSuccessStatusCode )
330
- {
331
- return new TrybeResponse (
332
- method ,
333
- uri ,
334
- response . IsSuccessStatusCode ,
335
- response . StatusCode ) ;
336
- }
337
- else
338
- {
339
- Error ? error = await GetTrybeError ( )
340
- . ConfigureAwait ( false ) ;
341
-
342
- return new TrybeResponse (
357
+ return ( new TrybeResponse (
343
358
method ,
344
359
uri ,
345
360
response . IsSuccessStatusCode ,
346
361
response . StatusCode ,
362
+ rateLimiting : rateLimiting ,
347
363
error : error
348
- ) ;
364
+ ) , stringContent ) ;
349
365
}
350
366
}
351
367
@@ -356,32 +372,6 @@ async Task<Error> GetTrybeError()
356
372
CancellationToken cancellationToken = default )
357
373
where TResponse : class
358
374
{
359
- async Task < Error > GetTrybeError ( )
360
- {
361
- Error error ;
362
- if ( response . Content is not null )
363
- {
364
- var result = await response . Content . ReadFromJsonAsync < ErrorContainer > (
365
- _deserializerOptions , cancellationToken )
366
- . ConfigureAwait ( false ) ;
367
-
368
- if ( result ? . Message is not { Length : > 0 } )
369
- {
370
- error = new ( Resources . ApiClient_UnknownResponse , result ? . Errors ) ;
371
- }
372
- else
373
- {
374
- error = new ( result . Message , result . Errors ) ;
375
- }
376
- }
377
- else
378
- {
379
- error = new Error ( Resources . ApiClient_NoErrorMessage ) ;
380
- }
381
-
382
- return error ;
383
- }
384
-
385
375
var rateLimiting = GetRateLimiting ( response ) ;
386
376
387
377
Stream ? content = null ;
@@ -404,11 +394,11 @@ async Task<Error> GetTrybeError()
404
394
{
405
395
DataContainer < TResponse > ? data = default ;
406
396
Meta ? meta = default ;
407
- if ( content is not null )
397
+ if ( content is not null || stringContent is { Length : > 0 } )
408
398
{
409
399
data = stringContent is { Length : > 0 }
410
400
? JsonSerializer . Deserialize < DataContainer < TResponse > > ( stringContent , _deserializerOptions )
411
- : await JsonSerializer . DeserializeAsync < DataContainer < TResponse > > ( content , _deserializerOptions ) . ConfigureAwait ( false ) ;
401
+ : await JsonSerializer . DeserializeAsync < DataContainer < TResponse > > ( content ! , _deserializerOptions ) . ConfigureAwait ( false ) ;
412
402
413
403
if ( data ? . Meta is not null )
414
404
{
@@ -434,8 +424,24 @@ async Task<Error> GetTrybeError()
434
424
}
435
425
else
436
426
{
437
- Error ? error = await GetTrybeError ( )
438
- . ConfigureAwait ( false ) ;
427
+ Error error ;
428
+ if ( stringContent is not null )
429
+ {
430
+ var result = JsonSerializer . Deserialize < ErrorContainer > ( stringContent , _deserializerOptions ) ;
431
+
432
+ if ( result ? . Message is not { Length : > 0 } )
433
+ {
434
+ error = new ( Resources . ApiClient_UnknownResponse , result ? . Errors ) ;
435
+ }
436
+ else
437
+ {
438
+ error = new ( result . Message , result . Errors ) ;
439
+ }
440
+ }
441
+ else
442
+ {
443
+ error = new Error ( Resources . ApiClient_NoErrorMessage ) ;
444
+ }
439
445
440
446
return ( new TrybeResponse < TResponse > (
441
447
method ,
0 commit comments