internal static HttpResponse Parse(string[] headerParts) { var statusLine = headerParts[0].Split(new[] { ' ' }, 3); if (statusLine.Length != 3) throw new ArgumentException("Invalid status line: " + headerParts[0]); var headers = new WebHeaderCollection(); for (int i = 1; i < headerParts.Length; i++) headers.SetInternal(headerParts[i]); return new HttpResponse( statusLine[1], statusLine[2], new Version(statusLine[0].Substring(5)), headers); }
internal void SendHeaders(bool closing, MemoryStream ms) { Encoding encoding = content_encoding; if (encoding == null) { encoding = Encoding.Default; } if (content_type != null) { if (content_encoding != null && content_type.IndexOf("charset=", StringComparison.Ordinal) == -1) { string enc_name = content_encoding.WebName; headers.SetInternal("Content-Type", content_type + "; charset=" + enc_name); } else { headers.SetInternal("Content-Type", content_type); } } if (headers["Server"] == null) { headers.SetInternal("Server", "Mono-HTTPAPI/1.0"); } CultureInfo inv = CultureInfo.InvariantCulture; if (headers["Date"] == null) { headers.SetInternal("Date", DateTime.UtcNow.ToString("r", inv)); } if (!chunked) { if (!cl_set && closing) { cl_set = true; content_length = 0; } if (cl_set) { headers.SetInternal("Content-Length", content_length.ToString(inv)); } } Version v = context.Request.ProtocolVersion; if (!cl_set && !chunked && v >= HttpVersion.Version11) { chunked = true; } /* Apache forces closing the connection for these status codes: * HttpStatusCode.BadRequest 400 * HttpStatusCode.RequestTimeout 408 * HttpStatusCode.LengthRequired 411 * HttpStatusCode.RequestEntityTooLarge 413 * HttpStatusCode.RequestUriTooLong 414 * HttpStatusCode.InternalServerError 500 * HttpStatusCode.ServiceUnavailable 503 */ bool conn_close = (status_code == 400 || status_code == 408 || status_code == 411 || status_code == 413 || status_code == 414 || status_code == 500 || status_code == 503); if (conn_close == false) { conn_close = !context.Request.KeepAlive; } // They sent both KeepAlive: true and Connection: close!? if (!keep_alive || conn_close) { headers.SetInternal("Connection", "close"); conn_close = true; } if (chunked) { headers.SetInternal("Transfer-Encoding", "chunked"); } //int reuses = context.Connection.Reuses; //if (reuses >= 100) //{ // _logger.Debug("HttpListenerResponse - keep alive has exceeded 100 uses and will be closed."); // force_close_chunked = true; // if (!conn_close) // { // headers.SetInternal("Connection", "close"); // conn_close = true; // } //} if (!conn_close) { if (context.Request.ProtocolVersion <= HttpVersion.Version10) { headers.SetInternal("Connection", "keep-alive"); } } if (location != null) { headers.SetInternal("Location", location); } if (cookies != null) { foreach (Cookie cookie in cookies) { headers.SetInternal("Set-Cookie", cookie.ToString()); } } using (StreamWriter writer = new StreamWriter(ms, encoding, 256, true)) { writer.Write("HTTP/{0} {1} {2}\r\n", version, status_code, status_description); string headers_str = headers.ToStringMultiValue(); writer.Write(headers_str); writer.Flush(); } int preamble = encoding.GetPreamble().Length; if (output_stream == null) { output_stream = context.Connection.GetResponseStream(); } /* Assumes that the ms was at position 0 */ ms.Position = preamble; HeadersSent = true; }
internal void AddHeader(string header) { int colon = header.IndexOf(':'); if (colon == -1 || colon == 0) { context.ErrorMessage = "Bad Request"; context.ErrorStatus = 400; return; } string name = header.Substring(0, colon).Trim(); string val = header.Substring(colon + 1).Trim(); string lower = name.ToLowerInvariant(); headers.SetInternal(name, val); switch (lower) { case "accept-language": user_languages = val.Split(','); // yes, only split with a ',' break; case "accept": accept_types = val.Split(','); // yes, only split with a ',' break; case "content-length": try { //TODO: max. content_length? content_length = Int64.Parse(val.Trim()); if (content_length < 0) { context.ErrorMessage = "Invalid Content-Length."; } cl_set = true; } catch { context.ErrorMessage = "Invalid Content-Length."; } break; case "content-type": { var contents = val.Split(';'); foreach (var content in contents) { var tmp = content.Trim(); if (tmp.StartsWith("charset")) { var charset = tmp.GetValue("="); if (charset != null && charset.Length > 0) { try { // Support upnp/dlna devices - CONTENT-TYPE: text/xml ; charset="utf-8"\r\n charset = charset.Trim('"'); var index = charset.IndexOf('"'); if (index != -1) { charset = charset.Substring(0, index); } content_encoding = Encoding.GetEncoding(charset); } catch { context.ErrorMessage = "Invalid Content-Type header: " + charset; } } break; } } } break; case "referer": try { referrer = new Uri(val); } catch { referrer = new Uri("http://someone.is.screwing.with.the.headers.com/"); } break; case "cookie": if (cookies == null) { cookies = new CookieCollection(); } string[] cookieStrings = val.Split(new char[] { ',', ';' }); Cookie current = null; int version = 0; foreach (string cookieString in cookieStrings) { string str = cookieString.Trim(); if (str.Length == 0) { continue; } if (str.StartsWith("$Version")) { version = Int32.Parse(Unquote(str.Substring(str.IndexOf('=') + 1))); } else if (str.StartsWith("$Path")) { if (current != null) { current.Path = str.Substring(str.IndexOf('=') + 1).Trim(); } } else if (str.StartsWith("$Domain")) { if (current != null) { current.Domain = str.Substring(str.IndexOf('=') + 1).Trim(); } } else if (str.StartsWith("$Port")) { if (current != null) { current.Port = str.Substring(str.IndexOf('=') + 1).Trim(); } } else { if (current != null) { cookies.Add(current); } current = new Cookie(); int idx = str.IndexOf('='); if (idx > 0) { current.Name = str.Substring(0, idx).Trim(); current.Value = str.Substring(idx + 1).Trim(); } else { current.Name = str.Trim(); current.Value = String.Empty; } current.Version = version; } } if (current != null) { cookies.Add(current); } break; } }