void WriteOutput(StreamWriter writer, string response, bool persistentConnection, HttpContext context, Action<StreamWriter> action) { bool binaryOutput = ms != null && ms.Length > 0; writer.WriteLine("HTTP/1.1 " + statusCode + " " + statusDescription); writer.WriteLine("Date: " + DateFormatter.FormatDateTimeGmt(DateTime.UtcNow)); writer.WriteLine("Expires: Thu, 01 Jan 1970 00:00:01 GMT"); writer.WriteLine("Server: " + Server.WebServerSoftwareName); writer.WriteLine("Cache-Control: no-cache, no-store, must-revalidate"); writer.WriteLine("Pragma: no-cache"); if (binaryOutput) writer.WriteLine("Content-Length: " + ms.Length); else writer.WriteLine("Content-Length: " + Encoding.UTF8.GetByteCount(response)); writer.WriteLine("Connection: " + (persistentConnection ? "keep-alive" : "close")); writer.WriteLine("Content-Type: " + contentType + (contentType.Contains("text/") ? "; charset=" + encodingString : string.Empty)); if (context != null) { if (context.Cookie.Count > 0) foreach (HttpCookieEntry cookie in context.Cookie) writer.WriteLine(string.Format("Set-Cookie: {0}", cookie)); if (context.Session.Entries != null) writer.WriteLine("Set-Cookie: " + SessionCookieKey + "=" + context.Session.Sid); } if (extraHeaders != null && extraHeaders.Count > 0) foreach (string extraHeader in extraHeaders) writer.WriteLine(extraHeader); if (action != null) action(writer); writer.WriteLine(); if (binaryOutput) { writer.Flush(); ms.Position = 0; ms.WriteTo(writer.BaseStream); } else { writer.WriteLine(response); writer.WriteLine(); } writer.Flush(); }
void Write500Error(StreamWriter writer, HttpContext context) { WriteError(writer, 500, "Internal Server Error", "<h1>Sorry, server is unavailable now, try later...</h1>", context, null); }
void WriteError(StreamWriter writer, int code, string status, string html, HttpContext context, Action<StreamWriter> action) { try { ms.Close(); ms = null; if (extraHeaders != null) extraHeaders.Clear(); ContentType = "text/html"; EncodingString = "UTF-8"; StatusCode = code; StatusDescription = status; string content = string.Format("<html><head><title>{0} - {1}</title></head><body>{2}</body></html>", code, status, html); WriteOutput(writer, content, false, context, action); } catch (IOException) { } writer.Dispose(); }
void Write404Error(StreamWriter writer, HttpContext context) { WriteError(writer, 404, "Not found", "<h1>Resource not found</h1>", context, null); }
void Write405Error(StreamWriter writer, HttpContext context) { WriteError(writer, 405, "Method Not Allowed", "<h1>Method not allowed</h1>", context, null); }
void Write401Error(StreamWriter writer, HttpContext context) { WriteError(writer, 401, "Unauthorised", "<h1>Unauthorised</h1>", context, delegate { switch (ci.AuthenticationMethod) { case AuthenticationMethod.Basic: writer.WriteLine("WWW-Authenticate: Basic realm=\"" + GetHeaderValue("Host") + "\""); break; case AuthenticationMethod.Digest: writer.WriteLine("WWW-Authenticate: " + ComposeDigestAuthenticationRequest()); break; } }); }
void Write400Error(StreamWriter writer, HttpContext context) { WriteError(writer, 400, "Bad Request", "<h1>Bad request</h1>", context, null); }
void InitializeSession(HttpContext context, string id) { if (!SessionStore.ContainsKey(id)) return; context.Session.Entries = SessionStore[id]; context.Session.Sid = id; context.Session.Entries.UpdateLastAccess(); }
void GetCookies(HttpContext context) { HttpCookie cookies = context.Cookie; foreach (string headerLine in requestHeaders) { if (headerLine.StartsWith("Cookie: ")) { string[] scookies = headerLine.Substring(8).Split(';'); foreach (string scookie in scookies) { string[] keyvaluepair = scookie.Split('='); if (keyvaluepair[0].Trim() == SessionCookieKey) InitializeSession(context, keyvaluepair[1]); else cookies[keyvaluepair[0].Trim()] = new HttpCookieEntry( keyvaluepair.Length > 0 ? keyvaluepair[1].Trim() : string.Empty, string.Empty); } } } }
public void Run() { bool persistentConnection; var reader = new StreamReader(stream); var writer = new StreamWriter(stream); do { var inbox = new StringBuilder(); outputStream = new StringBuilder(); ms = new MemoryStream(); bool firstLine = true; try { string line; while (!string.IsNullOrEmpty((line = reader.ReadLine()))) { if (firstLine) { ParseUrl(line); firstLine = false; } inbox.AppendLine(line); } } catch (IOException) { writer.Dispose(); return; } catch (IndexOutOfRangeException) { Write400Error(writer, null); return; } requestHeaders = ParseHeaders(inbox.ToString()); persistentConnection = IsPersistent(); if (httpMethod != "GET" && httpMethod != "POST") { Write405Error(writer, null); return; } if (httpMethod == "POST") { try { int inboxContentLength; int.TryParse(GetHeaderValue("Content-Length"), out inboxContentLength); if (inboxContentLength > 0) { if (GetHeaderValue("Content-Type").StartsWith("multipart/form-data")) { binaryRequest = new byte[inboxContentLength]; reader.BaseStream.Read(binaryRequest, 0, inboxContentLength); } else { var buffer = new char[inboxContentLength]; reader.Read(buffer, 0, inboxContentLength); requestBody = new string(buffer); } } } catch (IOException) { writer.Dispose(); return; } } if (string.IsNullOrEmpty(inbox.ToString())) { Write400Error(writer, null); return; } GetAuthorization(); if (ci.AuthenticationMethod != AuthenticationMethod.None && string.IsNullOrEmpty(ci.LogonUser)) { Write401Error(writer, null); return; } var context = new HttpContext(this); GetCookies(context); Type handlerType = Router.GetHandler(path); if (handlerType == null) { Write404Error(writer, null); return; } var page = HandlerActivator.Instance.GetHandler(handlerType); try { contentType = "text/html"; encodingString = "utf-8"; page.ProcessRequest(new HttpApplicationRuntime(context)); } catch (Exception) { Write500Error(writer, null); return; } string response = outputStream.ToString(); WriteOutput(writer, response, persistentConnection, context, null); } while (persistentConnection); writer.Dispose(); }