Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 9719572

Browse files
committed
Merge pull request #2705 from rajansingh10/myfeature
Fixing multi response header issue along with putting checks in http message parser.
2 parents 2013007 + adfcc89 commit 9719572

File tree

1 file changed

+75
-13
lines changed

1 file changed

+75
-13
lines changed

src/System.Net.Http/src/System/Net/Http/Unix/CurlCallbacks.cs

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ namespace System.Net.Http
2323
internal partial class CurlHandler
2424
{
2525
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;
2629

2730
private static Interop.libcurl.curl_readwrite_callback s_receiveHeadersCallback =
2831
(Interop.libcurl.curl_readwrite_callback) CurlReceiveHeadersCallback;
@@ -204,29 +207,88 @@ private static bool TryParseStatusLine(HttpResponseMessage response, string resp
204207
return false;
205208
}
206209

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+
207217
// Check if line begins with HTTP/1.1 or HTTP/1.0
208218
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] == '.'))
210222
{
211-
if (responseHeader[prefixLength + 2] == '1')
223+
if (responseHeader[versionIndex] == '1')
224+
{
225+
response.Version = HttpVersion.Version11;
226+
}
227+
else if (responseHeader[versionIndex] == '0')
212228
{
213-
response.Version = new Version(1, 1);
229+
response.Version = HttpVersion.Version10;
214230
}
215-
else if (responseHeader[prefixLength + 2] == '0')
231+
else
216232
{
217-
response.Version = new Version(1, 0);
233+
response.Version = new Version(0, 0);
218234
}
219235
}
220-
221-
// Parse first 3 characters after a space as status code
236+
else
237+
{
238+
response.Version = new Version(0, 0);
239+
}
240+
222241
// 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+
}
227290

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');
230292

231293
return true;
232294
}

0 commit comments

Comments
 (0)