@@ -90,10 +90,21 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont
9090 [ Serializable ]
9191 public class BadServerResponseException : Exception
9292 {
93+ public int StatusCode { get ; }
94+ public string InitialLine { get ; }
95+ public string Body { get ; }
96+
9397 public BadServerResponseException ( ) { }
9498
9599 public BadServerResponseException ( string message ) : base ( message ) { }
96100
101+ public BadServerResponseException ( string message , int statusCode , string initialLine , string body ) : base ( message )
102+ {
103+ StatusCode = statusCode ;
104+ InitialLine = initialLine ;
105+ Body = body ;
106+ }
107+
97108 public BadServerResponseException ( string message , Exception exception ) : base ( message , exception ) { }
98109
99110#if ! ( NET8_0_OR_GREATER )
@@ -195,11 +206,16 @@ private static string ReadLine(Stream stream)
195206 private static bool ReadHttpHeaders ( ref Stream stream , IWebProxy proxy , bool nodelay , int timeout_ms , List < string > headers = null )
196207 {
197208 // read headers/fields
198- string line = ReadLine ( stream ) , initialLine = line , transferEncodingField = null ;
209+ string line = ReadLine ( stream ) ;
210+ string initialLine = line ;
211+ string transferEncodingField = null ;
212+
199213 if ( string . IsNullOrEmpty ( initialLine ) ) // sanity check
200214 return false ;
215+
201216 if ( headers == null )
202217 headers = new List < string > ( ) ;
218+
203219 while ( ! string . IsNullOrWhiteSpace ( line ) ) // IsNullOrWhiteSpace also checks for empty string
204220 {
205221 line = line . TrimEnd ( '\r ' , '\n ' ) ;
@@ -211,6 +227,7 @@ private static bool ReadHttpHeaders(ref Stream stream, IWebProxy proxy, bool nod
211227
212228 // read chunks
213229 string entityBody = "" ;
230+
214231 if ( ! string . IsNullOrEmpty ( transferEncodingField ) )
215232 {
216233 int lastChunkSize = - 1 ;
@@ -246,13 +263,9 @@ private static bool ReadHttpHeaders(ref Stream stream, IWebProxy proxy, bool nod
246263 entityBody = entityBody . TrimEnd ( '\r ' , '\n ' ) ;
247264 headers . Add ( entityBody ) ; // keep entityBody if it's needed for Digest authentication (when qop="auth-int")
248265 }
249- else
250- {
251- // todo: handle other transfer types, in case "Transfer-Encoding: Chunked" isn't used
252- }
253266
254267 // handle server response
255- int code = getResultCode ( initialLine ) ;
268+ int code = GetResultCode ( initialLine ) ;
256269 switch ( code )
257270 {
258271 case 407 : // authentication error; caller must handle this case
@@ -268,17 +281,32 @@ private static bool ReadHttpHeaders(ref Stream stream, IWebProxy proxy, bool nod
268281 return true ; // headers need to be sent again
269282
270283 default :
284+ var contentLengthHeader = headers
285+ . FirstOrDefault ( h => h . StartsWith ( "Content-Length:" , StringComparison . InvariantCultureIgnoreCase ) ) ;
286+
287+ if ( contentLengthHeader != null && int . TryParse ( contentLengthHeader . Substring ( 15 ) . Trim ( ) , out var len ) )
288+ {
289+ byte [ ] bytes = new byte [ len ] ;
290+ int total = 0 ;
291+ int read ;
292+
293+ while ( total < len && ( read = stream . Read ( bytes , total , len - total ) ) > 0 )
294+ total += read ;
295+
296+ entityBody = Encoding . ASCII . GetString ( bytes ) ;
297+ }
298+
271299 stream . Close ( ) ;
272- throw new BadServerResponseException ( string . Format ( "Received error code {0} from the server" , initialLine ) ) ;
300+ throw new BadServerResponseException ( string . Format ( "Received error code {0} from the server" , initialLine ) , code , initialLine , entityBody ) ;
273301 }
274302
275303 return false ;
276304 }
277305
278- private static int getResultCode ( string line )
306+ private static int GetResultCode ( string line )
279307 {
280308 string [ ] bits = line . Split ( ' ' ) ;
281- return ( bits . Length < 2 ? 0 : Int32 . Parse ( bits [ 1 ] ) ) ;
309+ return bits . Length < 2 ? 0 : Int32 . Parse ( bits [ 1 ] ) ;
282310 }
283311
284312 public static bool UseSSL ( Uri uri )
@@ -651,7 +679,7 @@ private static void AuthenticateProxy(ref Stream stream, Uri uri, IWebProxy prox
651679 if ( authenticatedResponse . Count == 0 )
652680 throw new BadServerResponseException ( "No response from the proxy server after authentication attempt." ) ;
653681
654- switch ( getResultCode ( authenticatedResponse [ 0 ] ) )
682+ switch ( GetResultCode ( authenticatedResponse [ 0 ] ) )
655683 {
656684 case 200 :
657685 break ;
0 commit comments