@@ -23,6 +23,9 @@ namespace System.Net.Http
23
23
internal partial class CurlHandler
24
24
{
25
25
private const string s_httpPrefix = "HTTP/" ;
26
+ private static readonly char [ ] s_newLineCharArray = new char [ ] { HttpRuleParser . CR , HttpRuleParser . LF } ;
27
+ private const char SpaceChar = ' ' ;
28
+ private const int StatusCodeLength = 3 ;
26
29
27
30
private static Interop . libcurl . curl_readwrite_callback s_receiveHeadersCallback =
28
31
( Interop . libcurl . curl_readwrite_callback ) CurlReceiveHeadersCallback ;
@@ -204,29 +207,88 @@ private static bool TryParseStatusLine(HttpResponseMessage response, string resp
204
207
return false ;
205
208
}
206
209
210
+ // Clear the header if status line is recieved again. This signifies that there are multiple response headers (like in redirection).
211
+ response . Headers . Clear ( ) ;
212
+
213
+ response . Content . Headers . Clear ( ) ;
214
+
215
+ int responseHeaderLength = responseHeader . Length ;
216
+
207
217
// Check if line begins with HTTP/1.1 or HTTP/1.0
208
218
int prefixLength = s_httpPrefix . Length ;
209
- if ( ( responseHeader [ prefixLength ] == '1' ) && ( responseHeader [ prefixLength + 1 ] == '.' ) )
219
+ int versionIndex = prefixLength + 2 ;
220
+
221
+ if ( ( versionIndex < responseHeaderLength ) && ( responseHeader [ prefixLength ] == '1' ) && ( responseHeader [ prefixLength + 1 ] == '.' ) )
210
222
{
211
- if ( responseHeader [ prefixLength + 2 ] == '1' )
223
+ if ( responseHeader [ versionIndex ] == '1' )
224
+ {
225
+ response . Version = HttpVersion . Version11 ;
226
+ }
227
+ else if ( responseHeader [ versionIndex ] == '0' )
212
228
{
213
- response . Version = new Version ( 1 , 1 ) ;
229
+ response . Version = HttpVersion . Version10 ;
214
230
}
215
- else if ( responseHeader [ prefixLength + 2 ] == '0' )
231
+ else
216
232
{
217
- response . Version = new Version ( 1 , 0 ) ;
233
+ response . Version = new Version ( 0 , 0 ) ;
218
234
}
219
235
}
220
-
221
- // Parse first 3 characters after a space as status code
236
+ else
237
+ {
238
+ response . Version = new Version ( 0 , 0 ) ;
239
+ }
240
+
222
241
// TODO: Parsing errors are treated as fatal. Find right behaviour
223
- int statusCodeLength = 3 ;
224
- int codeIndex = responseHeader . IndexOf ( ' ' ) + 1 ;
225
- string strStatusCode = responseHeader . Substring ( codeIndex , statusCodeLength ) ;
226
- response . StatusCode = ( HttpStatusCode ) ( int . Parse ( strStatusCode ) ) ;
242
+
243
+ int spaceIndex = responseHeader . IndexOf ( SpaceChar ) ;
244
+
245
+ if ( spaceIndex > - 1 )
246
+ {
247
+ int codeStartIndex = spaceIndex + 1 ;
248
+ int statusCode = 0 ;
249
+
250
+ // Parse first 3 characters after a space as status code
251
+ if ( TryParseStatusCode ( responseHeader , codeStartIndex , out statusCode ) )
252
+ {
253
+ response . StatusCode = ( HttpStatusCode ) statusCode ;
254
+
255
+ int codeEndIndex = codeStartIndex + StatusCodeLength ;
256
+
257
+ int reasonPhraseIndex = codeEndIndex + 1 ;
258
+
259
+ if ( reasonPhraseIndex < responseHeaderLength && responseHeader [ codeEndIndex ] == SpaceChar )
260
+ {
261
+ int newLineCharIndex = responseHeader . IndexOfAny ( s_newLineCharArray , reasonPhraseIndex ) ;
262
+ int reasonPhraseEnd = newLineCharIndex >= 0 ? newLineCharIndex : responseHeaderLength ;
263
+ response . ReasonPhrase = responseHeader . Substring ( reasonPhraseIndex , reasonPhraseEnd - reasonPhraseIndex ) ;
264
+ }
265
+ }
266
+ }
267
+
268
+ return true ;
269
+ }
270
+
271
+ private static bool TryParseStatusCode ( string responseHeader , int statusCodeStartIndex , out int statusCode )
272
+ {
273
+ if ( statusCodeStartIndex + StatusCodeLength > responseHeader . Length )
274
+ {
275
+ statusCode = 0 ;
276
+ return false ;
277
+ }
278
+
279
+ char c100 = responseHeader [ statusCodeStartIndex ] ;
280
+ char c10 = responseHeader [ statusCodeStartIndex + 1 ] ;
281
+ char c1 = responseHeader [ statusCodeStartIndex + 2 ] ;
282
+
283
+ if ( c100 < '0' || c100 > '9' ||
284
+ c10 < '0' || c10 > '9' ||
285
+ c1 < '0' || c1 > '9' )
286
+ {
287
+ statusCode = 0 ;
288
+ return false ;
289
+ }
227
290
228
- // The remaining string after the space is the reason phrase
229
- response . ReasonPhrase = responseHeader . Substring ( codeIndex + statusCodeLength + 1 ) ;
291
+ statusCode = ( c100 - '0' ) * 100 + ( c10 - '0' ) * 10 + ( c1 - '0' ) ;
230
292
231
293
return true ;
232
294
}
0 commit comments