internal HttpRequestLine(HttpSocket hs) { string line; do { line = hs.ReadAsciiLine().Trim(); }while (line.Length == 0); string[] items = line.Split(sp, StringSplitOptions.RemoveEmptyEntries); if (items.Length != 3) { throw new HttpProtocolBroken("Unrecognized request line '" + line + "'"); } RequestLine = line; Method = items[0]; URI = items[1]; ProtocolVersion = ParserHelper.ParseProtocolVersion(items[2]); }
internal HttpStatusLine(HttpSocket hs) { string line; do { line = hs.ReadAsciiLine().Trim(); }while (line.Length == 0); string[] items = line.Split(sp, StringSplitOptions.RemoveEmptyEntries); // Note: the status line has three items: the HTTP protocol // version, the status code, and the reason phrase. // Only the reason phrase may be empty. if (items.Length < 2) { throw new HttpProtocolBroken("Unrecognized status line '" + line + "'"); } ProtocolVersion = ParserHelper.ParseProtocolVersion( items[0]); string code = items[1]; if (code.Length != 3 || !char.IsDigit(code[0])) // we only test the first character { throw new HttpProtocolBroken("Invalid status code '" + code + "'"); } //string Reason = rest of the string; // we don't need it StatusCode = int.Parse(code); StatusLine = line; }
/// <summary> /// Read and parse HTTP headers from a connected socket /// </summary> public HttpHeaders(HttpSocket source) : this() { StringBuilder sb = new StringBuilder(512); while (true) { var line = source.ReadAsciiLine(); if (line.Length == 0) { break; } sb.Append(line); sb.Append("\r\n"); // Note: if the header newline was // incorrectly formatted (i.e. LF instead of CRLF), // we correct it here. This is one point where our // proxy is not fully transparent. var iSplit = line.IndexOf(':'); if (iSplit <= 0) { throw new HttpProtocolBroken("No colon in HTTP header"); } // Header names are case-insensitive, but only some header // values are. string HeaderName = line.Substring(0, iSplit).Trim().ToLower(); string HeaderValue = line.Substring(iSplit + 1).Trim(); if (IsHeaderValueCaseInsensitive(HeaderName)) { HeaderValue = HeaderValue.ToLower(); } string previous_value = null; if (Headers.TryGetValue(HeaderName, out previous_value)) { // Duplicate headers: concatenate them // (RFC 2616, section 4.2) // However, this should only occur if the value of that // header is a comma-separated list. In the real world, // it has been observed that headers with // non-comma-separated values, such as Content-Length, *are* // in some rare cases repeated, so we should not concatenate // the values. if (!HeaderName.Equals("content-length")) { Headers[HeaderName] = previous_value + "," + HeaderValue; } } else { Headers[HeaderName] = HeaderValue; } } HeadersInOrder = sb.ToString(); // Parse a subset of the header values. // If headers are added, don't forget to update RemoveHeader // as well. Connection = ParseMultipleStringValues("connection"); ContentEncoding = ParseStringValue("content-encoding"); ContentLength = ParseIntValue("content-length"); Host = ParseStringValue("host"); ProxyConnection = ParseMultipleStringValues("proxy-connection"); Referer = ParseStringValue("referer"); TransferEncoding = ParseMultipleStringValues("transfer-encoding"); }