internal HttpResponseHeader(DataReader reader, IEnumerable<KeyDataPair<string>> headers, int responseCode, string message, HttpVersion version) { _reader = reader; Headers = new List<KeyDataPair<string>>(headers); ResponseCode = responseCode; Message = message; Version = version; if (ResponseCode != 304) { ContentLength = HttpParser.GetContentLength(Headers); ChunkedEncoding = HttpParser.IsChunkedEncoding(Headers); HasBody = true; } // Always trust a content-length if it exists if (Headers.Count(p => p.Name.Equals("Content-Length", StringComparison.OrdinalIgnoreCase)) == 0) { // Otherwise if version unknown, 1.0 or connection will close set then indicate we will read to the end if (Version.IsVersionUnknown || Version.IsVersion10 || (Headers.Count(p => p.Name.Equals("Connection", StringComparison.OrdinalIgnoreCase) && p.Value.Equals("close", StringComparison.OrdinalIgnoreCase)) > 0)) { ReadToEnd = true; } } }
internal HttpRequestHeader(DataReader reader, IEnumerable<KeyDataPair<string>> headers, string method, string path, HttpVersion version) { _reader = reader; Headers = new List<KeyDataPair<string>>(headers); Method = method; Path = path; Version = version; // These methods can't have a content length if(IsGet || IsHead) { ContentLength = 0; } else { ContentLength = HttpParser.GetContentLength(Headers); } }
/// <summary> /// Try and parse a string to a version /// </summary> /// <param name="version">The version string (should be HTTP/X.Y)</param> /// <param name="ret">The output parameter for the version</param> /// <returns>True if successfully parsed the verison</returns> public static bool TryParse(string version, out HttpVersion ret) { Regex re = new Regex(@"^http/([0-9])+\.([0-9]+)$", RegexOptions.IgnoreCase); Match m = re.Match(version); ret = new HttpVersion(); bool success = false; if (m.Success) { int major; int minor; if (int.TryParse(m.Groups[1].Value, out major) && int.TryParse(m.Groups[2].Value, out minor)) { ret = new HttpVersion(major, minor); success = true; } } return success; }
/// <summary> /// Read the response header /// </summary> /// <param name="reader">The data reader to read from</param> /// <param name="strictParsing">Use strict parsing rules</param> /// <param name="logger">The logger to write errors to</param> /// <exception cref="EndOfStreamException">Thrown when stream ends</exception> /// <returns>The http response header</returns> public static HttpResponseHeader ReadResponseHeader(DataReader reader, bool strictParsing, Logger logger) { // Read just first 4 chars string header = reader.ReadLine(BinaryEncoding.Instance, TextLineEnding.LineFeed, 4); // If no more data left then we end here if (header.Length == 0) { throw new EndOfStreamException(); } if (strictParsing) { CheckLineEnding(header); } if (header.Equals("http", StringComparison.OrdinalIgnoreCase)) { // Read to end of line header = header + reader.ReadLine(); HttpVersion ver = new HttpVersion(1, 0); string[] values = header.Trim().Split(new char[] { ' ' }, 3); if (values.Length < 2) { throw new HttpStreamParserException(String.Format(Properties.Resources.HttpParser_ResponseHeaderInvalid, header)); } if (!HttpVersion.TryParse(values[0], out ver)) { throw new HttpStreamParserException(Properties.Resources.HttpParser_InvalidHttpVersionString); } int responseCode; if (!int.TryParse(values[1], out responseCode)) { throw new HttpStreamParserException(Properties.Resources.HttpParser_InvalidHttpResponseCode); } return new HttpResponseHeader(reader, ReadHeaders(reader, strictParsing, logger), responseCode, values.Length > 2 ? values[2] : String.Empty, ver); } else { // Case where server probably responded with simple response even when we sent a full one return new HttpResponseHeader(reader, header); } }
private void ReturnResponse(HttpRequestHeader request, int responseCode, string message, string method, HttpVersion version, IEnumerable<KeyDataPair<string>> sendHeaders, DataAdapterToStream stm) { if (request != null) { FlushRequest(request); } HttpResponseDataChunk response = new HttpResponseDataChunk(); if (_config.Version10Proxy && !version.IsVersionUnknown) { response.Version = HttpVersion.Version10; } else { response.Version = version; } response.ResponseCode = responseCode; response.Message = message; response.FinalChunk = true; response.Body = new byte[0]; List<KeyDataPair<string>> headers = new List<KeyDataPair<string>>(sendHeaders); headers.Add(new KeyDataPair<string>("X-Proxy-Server", "CANAPE")); if (response.Body.Length > 0) { headers.Add(new KeyDataPair<string>("Content-Type", "text/html")); } response.Headers = headers.ToArray(); if (method.Equals("HEAD", StringComparison.OrdinalIgnoreCase)) { response.HeadResponse = true; } else if (method.Equals("CONNECT", StringComparison.OrdinalIgnoreCase)) { response.ConnectResponse = true; } response.WriteChunk(new DataWriter(stm)); }
private void ReturnResponse(HttpRequestHeader request, int responseCode, string message, string method, HttpVersion version, DataAdapterToStream stm) { ReturnResponse(request, responseCode, message, method, version, new KeyDataPair<string>[0], stm); }
/// <summary> /// Constructor /// </summary> /// <param name="headers">List of headers</param> /// <param name="version">The HTTP version</param> protected HttpDataChunk(IEnumerable<KeyDataPair<string>> headers, HttpVersion version) { Headers = headers.ToArray(); Version = version; Body = new byte[0]; }
internal HttpRequestHeader(DataReader reader, IEnumerable <KeyDataPair <string> > headers, string method, string path, HttpVersion version) { _reader = reader; Headers = new List <KeyDataPair <string> >(headers); Method = method; Path = path; Version = version; // These methods can't have a content length if (IsGet || IsHead) { ContentLength = 0; } else { ContentLength = HttpParser.GetContentLength(Headers); } }
/// <summary> /// Constructor /// </summary> /// <param name="headers">List of headers</param> /// <param name="version">The HTTP version</param> protected HttpDataChunk(IEnumerable <HttpHeader> headers, HttpVersion version) { Headers = headers.ToArray(); Version = version; Body = new byte[0]; }
/// <summary> /// Constructor /// </summary> /// <param name="headers">List of headers</param> /// <param name="version">The HTTP version</param> protected HttpDataChunk(IEnumerable <KeyDataPair <string> > headers, HttpVersion version) { Headers = headers.ToArray(); Version = version; Body = new byte[0]; }
private HttpResponseDataChunk BuildError(int error, string message, string method, HttpVersion version) { HttpResponseDataChunk response = new HttpResponseDataChunk(); response.Version = version; response.ResponseCode = error; response.Message = message; response.FinalChunk = true; response.Body = new byte[0]; List<KeyDataPair<string>> headers = new List<KeyDataPair<string>>(); headers.Add(new KeyDataPair<string>("X-Proxy-Server", "CANAPE")); response.Headers = headers.ToArray(); if (method.Equals("HEAD", StringComparison.OrdinalIgnoreCase)) { response.HeadResponse = true; } else if (method.Equals("CONNECT", StringComparison.OrdinalIgnoreCase)) { response.ConnectResponse = true; } return response; }