public static void Parse(Stream input, IHttpMessagePrologueParseSink sink) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (sink == null) { throw new ArgumentNullException(nameof(sink)); } if (!input.CanRead) { throw new ArgumentException(null, nameof(input)); } var lineBuilder = new StringBuilder(); string startLine; do { startLine = HttpLine.Read(input, lineBuilder)?.Trim(); if (startLine == null) { throw new FormatException("Missing HTTP request line or status response."); } }while (startLine.Length == 0); var match = Regex.Match(startLine, @"^HTTP/(0\.9|[1-9]\.[0-9])\x20+([1-5][0-9]{2})(?:\x20+(.+))?$"); if (match.Success) { var groups = match.Groups; var version = groups[1].Value; var statusCode = int.Parse(groups[2].Value, NumberStyles.None, CultureInfo.InvariantCulture); var reasonPhrase = groups[3].Value; sink.OnResponseLine(version, statusCode, reasonPhrase); } else if ((match = Regex.Match(startLine, @"^([!#$%&""'*.^_`|~0-9A-Za-z+-]+)\x20+([^\x20]+)(?:\x20+HTTP/([1-9]\.[0-9]))?$")).Success) { var groups = match.Groups; var method = groups[1].Value; var url = groups[2].Value; var version = groups[3].Success ? groups[3].Value : null; sink.OnRequestLine(method, url, version); } else { throw new FormatException("Invalid HTTP request line or status response: " + startLine); } foreach (var(name, value) in ReadHeaders(input, lineBuilder)) { sink.OnHeader(name, value); } }
static IEnumerable <KeyValuePair <string, string> > ReadHeaders(Stream input, StringBuilder lineBuilder) { string headerName = null; string headerValue = null; while (true) { var line = HttpLine.Read(input, lineBuilder); if (string.IsNullOrEmpty(line)) { break; } if (headerName != null && line[0] == ' ' || line[0] == '\t') { headerValue = headerValue + line; } else { if (headerName != null) { yield return(new KeyValuePair <string, string>(headerName, headerValue)); } var pair = line.Split(Colon, 2); if (pair.Length != 2) { continue; } headerName = pair[0].Trim(Whitespace); headerValue = pair[1].TrimStart(Whitespace); } } if (headerName != null) { yield return(new KeyValuePair <string, string>(headerName, headerValue)); } }