@@ -6,47 +6,99 @@ namespace Dibix.Http.Client
66{
77 public class HttpRequestTracer
88 {
9- public bool MaskSensitiveData { get ; set ; } = true ;
9+ public bool MaskSensitiveContent { get ; } = true ;
1010 public HttpRequestTrace LastRequest { get ; private set ; }
1111
12- internal async Task TraceRequestAsync ( HttpRequestMessage requestMessage )
12+ public HttpRequestTracer ( ) { }
13+ public HttpRequestTracer ( bool maskSensitiveContent )
1314 {
14- string requestContentText = await this . GetRequestContentTextAsync ( requestMessage ) . ConfigureAwait ( false ) ;
15- string formattedRequestText = this . FormatRequest ( requestMessage , requestContentText ) ;
16- await this . TraceRequestAsync ( requestMessage , formattedRequestText ) . ConfigureAwait ( false ) ;
15+ this . MaskSensitiveContent = maskSensitiveContent ;
16+ }
17+
18+ internal async Task TraceRequestMessageAsync ( HttpRequestMessage requestMessage )
19+ {
20+ await this . CollectLastRequest ( requestMessage ) . ConfigureAwait ( false ) ;
21+ await this . TraceRequestAsync ( requestMessage ) . ConfigureAwait ( false ) ;
1722 }
1823
19- internal async Task TraceResponseAsync ( HttpResponseMessage responseMessage , TimeSpan duration )
24+ internal async Task TraceResponseMessageAsync ( HttpResponseMessage responseMessage , TimeSpan duration )
2025 {
21- string responseContentTest = await this . GetResponseContentTextAsync ( responseMessage ) . ConfigureAwait ( false ) ;
22- string formattedResponseText = this . FormatResponse ( responseMessage , responseContentTest ) ;
23- await this . TraceResponseAsync ( responseMessage , formattedResponseText , duration ) . ConfigureAwait ( false ) ;
26+ await CompleteLastRequest ( responseMessage , duration ) . ConfigureAwait ( false ) ;
27+ await this . TraceResponseAsync ( responseMessage , duration ) ;
2428 }
2529
26- protected virtual Task TraceRequestAsync ( HttpRequestMessage requestMessage , string formattedRequestText )
30+ protected virtual Task TraceRequestAsync ( HttpRequestMessage requestMessage ) => Task . CompletedTask ;
31+
32+ protected virtual Task TraceResponseAsync ( HttpResponseMessage responseMessage , TimeSpan duration ) => Task . CompletedTask ;
33+
34+ protected virtual bool ShouldBufferRequestContent ( HttpRequestMessage requestMessage ) => false ;
35+
36+ protected virtual bool ShouldBufferResponseContent ( HttpRequestMessage requestMessage ) => false ;
37+
38+ private async Task CollectLastRequest ( HttpRequestMessage requestMessage )
2739 {
40+ string formattedRequestText = await this . GetFormattedRequestContent ( requestMessage ) . ConfigureAwait ( false ) ;
2841 this . LastRequest = new HttpRequestTrace ( requestMessage , formattedRequestText ) ;
29- return Task . CompletedTask ;
3042 }
3143
32- protected virtual Task TraceResponseAsync ( HttpResponseMessage responseMessage , string formattedResponseText , TimeSpan duration )
44+ private async Task CompleteLastRequest ( HttpResponseMessage responseMessage , TimeSpan duration )
3345 {
3446 if ( this . LastRequest == null )
3547 throw new InvalidOperationException ( "Request not initialized" ) ;
3648
49+ string formattedResponseText = await this . GetFormattedResponseContent ( responseMessage ) . ConfigureAwait ( false ) ;
3750 this . LastRequest . ResponseMessage = responseMessage ;
3851 this . LastRequest . FormattedResponseText = formattedResponseText ;
3952 this . LastRequest . Duration = duration ;
40-
41- return Task . CompletedTask ;
53+
54+ // Since non successful status code will throw an exception,
55+ // it is now safe to restore the request content, that was not previously captured
56+ HttpRequestMessage requestMessage = responseMessage . RequestMessage ;
57+ if ( ! this . ShouldBufferRequestContent ( requestMessage ) && ! responseMessage . IsSuccessStatusCode )
58+ {
59+ string requestContentText = await GetRequestContentTextAsync ( requestMessage , bufferRequestContent : true ) . ConfigureAwait ( false ) ;
60+ this . LastRequest . FormattedRequestText = this . FormatRequest ( requestMessage , requestContentText ) ;
61+ }
62+ }
63+
64+ private async Task < string > GetFormattedRequestContent ( HttpRequestMessage requestMessage )
65+ {
66+ bool bufferRequestContent = this . ShouldBufferRequestContent ( requestMessage ) ;
67+ string requestContentText = await GetRequestContentTextAsync ( requestMessage , bufferRequestContent ) . ConfigureAwait ( false ) ;
68+ string formattedRequestText = this . FormatRequest ( requestMessage , requestContentText ) ;
69+ return formattedRequestText ;
70+ }
71+
72+ private async Task < string > GetFormattedResponseContent ( HttpResponseMessage responseMessage )
73+ {
74+ bool bufferResponseContent = this . ShouldBufferResponseContent ( responseMessage . RequestMessage ) || ! responseMessage . IsSuccessStatusCode ;
75+ string responseContentTest = await GetResponseContentTextAsync ( responseMessage , bufferResponseContent ) . ConfigureAwait ( false ) ;
76+ string formattedResponseText = HttpMessageFormatter . Format ( responseMessage , responseContentTest ) ;
77+ return formattedResponseText ;
78+ }
79+
80+ private string FormatRequest ( HttpRequestMessage requestMessage , string requestContentText ) => HttpMessageFormatter . Format ( requestMessage , requestContentText , this . MaskSensitiveContent ) ;
81+
82+ private static async Task < string > GetRequestContentTextAsync ( HttpRequestMessage requestMessage , bool bufferRequestContent )
83+ {
84+ if ( requestMessage . Content == null )
85+ return null ;
86+
87+ if ( ! bufferRequestContent )
88+ return "<Request content unavailable>" ;
89+
90+ return await requestMessage . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ;
4291 }
4392
44- protected virtual string FormatRequest ( HttpRequestMessage requestMessage , string requestContentText ) => HttpMessageFormatter . Format ( requestMessage , requestContentText , this . MaskSensitiveData ) ;
93+ private static async Task < string > GetResponseContentTextAsync ( HttpResponseMessage responseMessage , bool bufferResponseContent )
94+ {
95+ if ( responseMessage . Content == null )
96+ return null ;
4597
46- protected virtual string FormatResponse ( HttpResponseMessage responseMessage , string responseContentTest ) => HttpMessageFormatter . Format ( responseMessage , responseContentTest ) ;
98+ if ( ! bufferResponseContent )
99+ return "<Response content unavailable>" ;
47100
48- protected virtual async Task < string > GetRequestContentTextAsync ( HttpRequestMessage requestMessage ) => requestMessage . Content != null ? await requestMessage . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) : null ;
49-
50- protected virtual Task < string > GetResponseContentTextAsync ( HttpResponseMessage responseMessage ) => responseMessage . Content . ReadAsStringAsync ( ) ;
101+ return await responseMessage . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ;
102+ }
51103 }
52104}
0 commit comments