@@ -7,6 +7,7 @@ namespace NamespacePrefixPlaceholder.PowerShell
77 using Newtonsoft . Json ;
88 using System ;
99 using System . Collections . Generic ;
10+ using System . IO ;
1011 using System . Linq ;
1112 using System . Net . Http ;
1213 using System . Net . Http . Headers ;
@@ -17,22 +18,54 @@ namespace NamespacePrefixPlaceholder.PowerShell
1718
1819 public static class HttpMessageLogFormatter
1920 {
21+ internal static async Task < HttpRequestMessage > CloneAsync ( this HttpRequestMessage originalRequest )
22+ {
23+ var newRequest = new HttpRequestMessage ( originalRequest . Method , originalRequest . RequestUri ) ;
24+
25+ // Copy requestClone headers.
26+ foreach ( var header in originalRequest . Headers )
27+ newRequest . Headers . TryAddWithoutValidation ( header . Key , header . Value ) ;
28+
29+ // Copy requestClone properties.
30+ foreach ( var property in originalRequest . Properties )
31+ newRequest . Properties . Add ( property ) ;
32+
33+ // Set Content if previous requestClone had one.
34+ if ( originalRequest . Content != null )
35+ {
36+ // HttpClient doesn't rewind streams and we have to explicitly do so.
37+ await originalRequest . Content . ReadAsStreamAsync ( ) . ContinueWith ( t =>
38+ {
39+ if ( t . Result . CanSeek )
40+ t . Result . Seek ( 0 , SeekOrigin . Begin ) ;
41+
42+ newRequest . Content = new StreamContent ( t . Result ) ;
43+ } ) . ConfigureAwait ( false ) ;
44+
45+ // Copy content headers.
46+ if ( originalRequest . Content . Headers != null )
47+ foreach ( var contentHeader in originalRequest . Content . Headers )
48+ newRequest . Content . Headers . TryAddWithoutValidation ( contentHeader . Key , contentHeader . Value ) ;
49+ }
50+ return newRequest ;
51+ }
52+
2053 public static async Task < string > GetHttpRequestLogAsync ( HttpRequestMessage request )
2154 {
2255 if ( request == null ) return string . Empty ;
23-
56+ var requestClone = await request . CloneAsync ( ) . ConfigureAwait ( false ) ;
2457 string body = string . Empty ;
2558 try
2659 {
27- body = ( request . Content == null ) ? string . Empty : FormatString ( await request . Content . ReadAsStringAsync ( ) ) ;
60+ body = ( requestClone . Content == null ) ? string . Empty : FormatString ( await requestClone . Content . ReadAsStringAsync ( ) ) ;
2861 }
2962 catch { }
3063
3164 StringBuilder stringBuilder = new StringBuilder ( ) ;
3265 stringBuilder . AppendLine ( $ "============================ HTTP REQUEST ============================{ Environment . NewLine } ") ;
33- stringBuilder . AppendLine ( $ "HTTP Method:{ Environment . NewLine } { request . Method . ToString ( ) } { Environment . NewLine } ") ;
34- stringBuilder . AppendLine ( $ "Absolute Uri:{ Environment . NewLine } { request . RequestUri . ToString ( ) } { Environment . NewLine } ") ;
35- stringBuilder . AppendLine ( $ "Headers:{ Environment . NewLine } { HeadersToString ( ConvertHttpHeadersToCollection ( request . Headers ) ) } { Environment . NewLine } ") ;
66+ stringBuilder . AppendLine ( $ "HTTP Method:{ Environment . NewLine } { requestClone . Method . ToString ( ) } { Environment . NewLine } ") ;
67+ stringBuilder . AppendLine ( $ "Absolute Uri:{ Environment . NewLine } { requestClone . RequestUri . ToString ( ) } { Environment . NewLine } ") ;
68+ stringBuilder . AppendLine ( $ "Headers:{ Environment . NewLine } { HeadersToString ( ConvertHttpHeadersToCollection ( requestClone . Headers ) ) } { Environment . NewLine } ") ;
3669 stringBuilder . AppendLine ( $ "Body:{ Environment . NewLine } { SanitizeBody ( body ) } { Environment . NewLine } ") ;
3770 return stringBuilder . ToString ( ) ;
3871 }
0 commit comments