From d75ea841eb73fd8c25f378614b360583e3e843b2 Mon Sep 17 00:00:00 2001 From: Onyeka Obi Date: Fri, 13 Mar 2015 14:36:22 -0700 Subject: [PATCH 1/2] Modernized --- Fiddle.html | 8 ++ Properties/AssemblyInfo.cs | 1 - SimpleHttpServer.cs | 268 +++++++++++++++++++------------------ SimpleHttpServer.csproj | 5 + 4 files changed, 148 insertions(+), 134 deletions(-) create mode 100755 Fiddle.html diff --git a/Fiddle.html b/Fiddle.html new file mode 100755 index 0000000..67ab500 --- /dev/null +++ b/Fiddle.html @@ -0,0 +1,8 @@ + + + Hello Page + + +

Hello World!

+ + \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 8213c6f..7b563d6 100755 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/SimpleHttpServer.cs b/SimpleHttpServer.cs index 66b1067..99b0c04 100755 --- a/SimpleHttpServer.cs +++ b/SimpleHttpServer.cs @@ -1,243 +1,250 @@ -using System; -using System.Collections; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Threading; - +using System; +using System.Collections; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Threading; + // offered to the public domain for any use with no restriction // and also with no warranty of any kind, please enjoy. - David Jeske. // simple HTTP explanation // http://www.jmarshall.com/easy/http/ -namespace Bend.Util { +namespace Minimalistic { public class HttpProcessor { - public TcpClient socket; - public HttpServer srv; + public TcpClient Socket; + public HttpServer Srv; private Stream inputStream; - public StreamWriter outputStream; - - public String http_method; - public String http_url; - public String http_protocol_versionstring; - public Hashtable httpHeaders = new Hashtable(); - - - private static int MAX_POST_SIZE = 10 * 1024 * 1024; // 10MB - - public HttpProcessor(TcpClient s, HttpServer srv) { - this.socket = s; - this.srv = srv; + public StreamWriter OutputStream; + + public String HttpMethod; + public String HttpUrl; + public String HttpProtocolVersionstring; + public Hashtable HttpHeaders = new Hashtable(); + + + private const int MaxPostSize = 10*1024*1024; // 10MB + + public HttpProcessor(TcpClient s, HttpServer srv) { + Socket = s; + Srv = srv; } - private string streamReadLine(Stream inputStream) { - int next_char; - string data = ""; + private static string StreamReadLine(Stream inputStream) { + var data = ""; while (true) { - next_char = inputStream.ReadByte(); - if (next_char == '\n') { break; } - if (next_char == '\r') { continue; } - if (next_char == -1) { Thread.Sleep(1); continue; }; - data += Convert.ToChar(next_char); + var nextChar = inputStream.ReadByte(); + if (nextChar == '\n') { break; } + switch (nextChar) + { + case '\r': + continue; + case -1: + Thread.Sleep(1); + continue; + } + data += Convert.ToChar(nextChar); } return data; } - public void process() { + public void Process() { // we can't use a StreamReader for input, because it buffers up extra data on us inside it's // "processed" view of the world, and we want the data raw after the headers - inputStream = new BufferedStream(socket.GetStream()); + inputStream = new BufferedStream(Socket.GetStream()); // we probably shouldn't be using a streamwriter for all output from handlers either - outputStream = new StreamWriter(new BufferedStream(socket.GetStream())); + OutputStream = new StreamWriter(new BufferedStream(Socket.GetStream())); try { - parseRequest(); - readHeaders(); - if (http_method.Equals("GET")) { - handleGETRequest(); - } else if (http_method.Equals("POST")) { - handlePOSTRequest(); + ParseRequest(); + ReadHeaders(); + if (HttpMethod.Equals("GET")) { + HandleGetRequest(); + } else if (HttpMethod.Equals("POST")) { + HandlePostRequest(); } } catch (Exception e) { Console.WriteLine("Exception: " + e.ToString()); - writeFailure(); + WriteFailure(); } - outputStream.Flush(); + OutputStream.Flush(); // bs.Flush(); // flush any remaining output - inputStream = null; outputStream = null; // bs = null; - socket.Close(); + inputStream = null; OutputStream = null; // bs = null; + Socket.Close(); } - public void parseRequest() { - String request = streamReadLine(inputStream); - string[] tokens = request.Split(' '); + public void ParseRequest() { + var request = StreamReadLine(inputStream); + var tokens = request.Split(' '); if (tokens.Length != 3) { throw new Exception("invalid http request line"); } - http_method = tokens[0].ToUpper(); - http_url = tokens[1]; - http_protocol_versionstring = tokens[2]; + HttpMethod = tokens[0].ToUpper(); + HttpUrl = tokens[1]; + HttpProtocolVersionstring = tokens[2]; Console.WriteLine("starting: " + request); } - public void readHeaders() { + public void ReadHeaders() { Console.WriteLine("readHeaders()"); String line; - while ((line = streamReadLine(inputStream)) != null) { + while ((line = StreamReadLine(inputStream)) != null) { if (line.Equals("")) { Console.WriteLine("got headers"); return; } - int separator = line.IndexOf(':'); + var separator = line.IndexOf(':'); if (separator == -1) { throw new Exception("invalid http header line: " + line); } - String name = line.Substring(0, separator); - int pos = separator + 1; + var name = line.Substring(0, separator); + var pos = separator + 1; while ((pos < line.Length) && (line[pos] == ' ')) { pos++; // strip any spaces } - string value = line.Substring(pos, line.Length - pos); + var value = line.Substring(pos, line.Length - pos); Console.WriteLine("header: {0}:{1}",name,value); - httpHeaders[name] = value; + HttpHeaders[name] = value; } } - public void handleGETRequest() { - srv.handleGETRequest(this); + public void HandleGetRequest() { + Srv.HandleGetRequest(this); } - private const int BUF_SIZE = 4096; - public void handlePOSTRequest() { + private const int BufSize = 4096; + public void HandlePostRequest() { // this post data processing just reads everything into a memory stream. // this is fine for smallish things, but for large stuff we should really // hand an input stream to the request processor. However, the input stream // we hand him needs to let him see the "end of the stream" at this content // length, because otherwise he won't know when he's seen it all! - Console.WriteLine("get post data start"); - int content_len = 0; - MemoryStream ms = new MemoryStream(); - if (this.httpHeaders.ContainsKey("Content-Length")) { - content_len = Convert.ToInt32(this.httpHeaders["Content-Length"]); - if (content_len > MAX_POST_SIZE) { + Console.WriteLine("get post data start"); + var ms = new MemoryStream(); + if (HttpHeaders.ContainsKey("Content-Length")) { + var contentLen = Convert.ToInt32(HttpHeaders["Content-Length"]); + if (contentLen > MaxPostSize) { throw new Exception( String.Format("POST Content-Length({0}) too big for this simple server", - content_len)); + contentLen)); } - byte[] buf = new byte[BUF_SIZE]; - int to_read = content_len; - while (to_read > 0) { - Console.WriteLine("starting Read, to_read={0}",to_read); + var buf = new byte[BufSize]; + var toRead = contentLen; + while (toRead > 0) { + Console.WriteLine("starting Read, to_read={0}",toRead); - int numread = this.inputStream.Read(buf, 0, Math.Min(BUF_SIZE, to_read)); + var numread = inputStream.Read(buf, 0, Math.Min(BufSize, toRead)); Console.WriteLine("read finished, numread={0}", numread); - if (numread == 0) { - if (to_read == 0) { + if (numread == 0) + { + if (toRead == 0) { break; - } else { - throw new Exception("client disconnected during post"); - } - } - to_read -= numread; + } + throw new Exception("client disconnected during post"); + } + toRead -= numread; ms.Write(buf, 0, numread); } ms.Seek(0, SeekOrigin.Begin); } Console.WriteLine("get post data end"); - srv.handlePOSTRequest(this, new StreamReader(ms)); + Srv.HandlePostRequest(this, new StreamReader(ms)); } - public void writeSuccess(string content_type="text/html") { + public void WriteSuccess(string contentType="text/html") { // this is the successful HTTP response line - outputStream.WriteLine("HTTP/1.0 200 OK"); + OutputStream.WriteLine("HTTP/1.0 200 OK"); // these are the HTTP headers... - outputStream.WriteLine("Content-Type: " + content_type); - outputStream.WriteLine("Connection: close"); + OutputStream.WriteLine("Content-Type: " + contentType); + OutputStream.WriteLine("Connection: close"); // ..add your own headers here if you like - outputStream.WriteLine(""); // this terminates the HTTP headers.. everything after this is HTTP body.. + OutputStream.WriteLine(""); // this terminates the HTTP headers.. everything after this is HTTP body.. } - public void writeFailure() { + public void WriteFailure() { // this is an http 404 failure response - outputStream.WriteLine("HTTP/1.0 404 File not found"); + OutputStream.WriteLine("HTTP/1.0 404 File not found"); // these are the HTTP headers - outputStream.WriteLine("Connection: close"); + OutputStream.WriteLine("Connection: close"); // ..add your own headers here - outputStream.WriteLine(""); // this terminates the HTTP headers. + OutputStream.WriteLine(""); // this terminates the HTTP headers. } } public abstract class HttpServer { - protected int port; - TcpListener listener; - bool is_active = true; - - public HttpServer(int port) { - this.port = port; + protected int Port; + TcpListener listener; + + protected HttpServer(int port) { + Port = port; } - public void listen() { - listener = new TcpListener(port); + public void Listen() { + listener = new TcpListener(Dns.GetHostAddresses("localhost").First(),Port); listener.Start(); - while (is_active) { - TcpClient s = listener.AcceptTcpClient(); - HttpProcessor processor = new HttpProcessor(s, this); - Thread thread = new Thread(new ThreadStart(processor.process)); + while (true) { + var s = listener.AcceptTcpClient(); + var processor = new HttpProcessor(s, this); + var thread = new Thread(processor.Process); thread.Start(); Thread.Sleep(1); } } - public abstract void handleGETRequest(HttpProcessor p); - public abstract void handlePOSTRequest(HttpProcessor p, StreamReader inputData); + public abstract void HandleGetRequest(HttpProcessor p); + public abstract void HandlePostRequest(HttpProcessor p, StreamReader inputData); } public class MyHttpServer : HttpServer { public MyHttpServer(int port) : base(port) { } - public override void handleGETRequest (HttpProcessor p) + public override void HandleGetRequest (HttpProcessor p) { - if (p.http_url.Equals ("/Test.png")) { - Stream fs = File.Open("../../Test.png",FileMode.Open); + if (p.HttpUrl.Equals ("/Fiddle.html")) { + Stream fs = File.Open("Fiddle.html",FileMode.Open); - p.writeSuccess("image/png"); - fs.CopyTo (p.outputStream.BaseStream); - p.outputStream.BaseStream.Flush (); + p.WriteSuccess(); + fs.CopyTo (p.OutputStream.BaseStream); + //p.OutputStream.BaseStream.Flush (); + p.OutputStream.Flush(); + return; } - Console.WriteLine("request: {0}", p.http_url); - p.writeSuccess(); - p.outputStream.WriteLine("

test server

"); - p.outputStream.WriteLine("Current Time: " + DateTime.Now.ToString()); - p.outputStream.WriteLine("url : {0}", p.http_url); + Console.WriteLine("request: {0}", p.HttpUrl); + p.WriteSuccess(); + p.OutputStream.WriteLine("

test server

"); + p.OutputStream.WriteLine("Current Time: " + DateTime.Now.ToString(CultureInfo.InvariantCulture)); + p.OutputStream.WriteLine("url : {0}", p.HttpUrl); - p.outputStream.WriteLine("
"); - p.outputStream.WriteLine(""); - p.outputStream.WriteLine(""); - p.outputStream.WriteLine("
"); + p.OutputStream.WriteLine("
"); + p.OutputStream.WriteLine(""); + p.OutputStream.WriteLine(""); + p.OutputStream.WriteLine("
"); } - public override void handlePOSTRequest(HttpProcessor p, StreamReader inputData) { - Console.WriteLine("POST request: {0}", p.http_url); - string data = inputData.ReadToEnd(); + public override void HandlePostRequest(HttpProcessor p, StreamReader inputData) { + Console.WriteLine("POST request: {0}", p.HttpUrl); + var data = inputData.ReadToEnd(); - p.writeSuccess(); - p.outputStream.WriteLine("

test server

"); - p.outputStream.WriteLine("return

"); - p.outputStream.WriteLine("postbody:

{0}
", data); + p.WriteSuccess(); + p.OutputStream.WriteLine("

test server

"); + p.OutputStream.WriteLine("return

"); + p.OutputStream.WriteLine("postbody:

{0}
", data); } @@ -245,13 +252,8 @@ public override void handlePOSTRequest(HttpProcessor p, StreamReader inputData) public class TestMain { public static int Main(String[] args) { - HttpServer httpServer; - if (args.GetLength(0) > 0) { - httpServer = new MyHttpServer(Convert.ToInt16(args[0])); - } else { - httpServer = new MyHttpServer(8080); - } - Thread thread = new Thread(new ThreadStart(httpServer.listen)); + var httpServer = args.GetLength(0) > 0 ? new MyHttpServer(Convert.ToInt16(args[0])) : new MyHttpServer(8080); + var thread = new Thread(httpServer.Listen); thread.Start(); return 0; } diff --git a/SimpleHttpServer.csproj b/SimpleHttpServer.csproj index 9e038c1..a9bbd0c 100644 --- a/SimpleHttpServer.csproj +++ b/SimpleHttpServer.csproj @@ -44,6 +44,11 @@ + + + Always + +