Mercurial > hg > ucis.core
comparison Net/HTTP.cs @ 0:3ab940a0c7a0
Initial commit
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Tue, 11 Sep 2012 16:28:53 +0200 |
parents | |
children | 0cc7be03775f |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3ab940a0c7a0 |
---|---|
1 using System; | |
2 using System.Collections.Generic; | |
3 using System.IO; | |
4 using System.Text; | |
5 using System.Threading; | |
6 | |
7 namespace UCIS.Net.HTTP { | |
8 public class HTTPServer : TCPServer.IModule { | |
9 public Dictionary<string, HTTPContent> Content = new Dictionary<string, HTTPContent>(StringComparer.InvariantCultureIgnoreCase); | |
10 public HTTPContent DefaultContent = null; | |
11 | |
12 public bool Accept(TCPStream Stream) { | |
13 StreamReader StreamReader = new StreamReader(Stream, Encoding.ASCII); | |
14 String Line = StreamReader.ReadLine(); | |
15 String[] Request = Line.Split(' '); | |
16 | |
17 //Console.WriteLine("HTTP.Server.Accept Request: " + Line); | |
18 | |
19 if (Request == null || Request.Length < 2 || Request[0] != "GET" || Request[1][0] != '/') { | |
20 //Console.WriteLine("HTTP.Server.Start Bad request"); | |
21 SendError(Stream, 400); | |
22 return true; | |
23 } | |
24 | |
25 Request = Request[1].Split(new Char[] { '?' }, 2); | |
26 HTTPContent content; | |
27 if (Content.TryGetValue(Request[0], out content)) { | |
28 } else if (DefaultContent != null) { | |
29 content = DefaultContent; | |
30 } else { | |
31 SendError(Stream, 404); | |
32 return true; | |
33 } | |
34 HTTPContext Context = new HTTPContext(); | |
35 Context.Stream = Stream; | |
36 Context.Request = new HTTPRequest(); | |
37 Context.Request.Method = Method.GET; | |
38 Context.Request.Path = Request[0]; | |
39 if (Request.Length == 2) { | |
40 Context.Request.Query = Request[1]; | |
41 } else { | |
42 Context.Request.Query = null; | |
43 } | |
44 HTTPContent.Result ServeResult = content.Serve(Context); | |
45 | |
46 if (ServeResult == HTTPContent.Result.OK_KEEPALIVE) { | |
47 return false; | |
48 } else if (!(ServeResult == HTTPContent.Result.OK_CLOSE)) { | |
49 SendError(Stream, (int)ServeResult); | |
50 } | |
51 return true; | |
52 } | |
53 | |
54 public static void SendError(Stream Stream, int ErrorCode) { | |
55 string ErrorText = null; | |
56 switch (ErrorCode) { | |
57 case 400: | |
58 ErrorText = "The request could not be understood by the server due to malformed syntax."; | |
59 break; | |
60 case 404: | |
61 ErrorText = "The requested file can not be found."; | |
62 break; | |
63 default: | |
64 ErrorText = "Unknown error code: " + ErrorCode.ToString() + "."; | |
65 break; | |
66 } | |
67 SendHeader(Stream, ErrorCode, "text/plain", ErrorText.Length); | |
68 WriteLine(Stream, ErrorText); | |
69 Thread.Sleep(100); | |
70 return; | |
71 } | |
72 | |
73 public static void SendHeader(Stream Stream, int ResultCode, string ContentType) { | |
74 SendHeader(Stream, ResultCode, ContentType, -1); | |
75 } | |
76 public static void SendHeader(Stream Stream, int ResultCode, string ContentType, int ContentLength) { | |
77 //ResultCode = 200, ContentType = null, ContentLength = -1 | |
78 string ResultString; | |
79 switch (ResultCode) { | |
80 case 200: ResultString = "OK"; break; | |
81 case 400: ResultString = "Bad Request"; break; | |
82 case 404: ResultString = "Not found"; break; | |
83 default: ResultString = "Unknown"; break; | |
84 } | |
85 WriteLine(Stream, "HTTP/1.1 " + ResultCode.ToString() + " " + ResultString); | |
86 WriteLine(Stream, "Expires: Mon, 26 Jul 1990 05:00:00 GMT"); | |
87 WriteLine(Stream, "Cache-Control: no-store, no-cache, must-revalidate"); | |
88 WriteLine(Stream, "Cache-Control: post-check=0, pre-check=0"); | |
89 WriteLine(Stream, "Pragma: no-cache"); | |
90 WriteLine(Stream, "Server: UCIS Simple Webserver"); | |
91 WriteLine(Stream, "Connection: Close"); | |
92 if ((ContentType != null)) WriteLine(Stream, "Content-Type: " + ContentType); | |
93 if (ContentLength != -1) WriteLine(Stream, "Content-Length: " + ContentLength.ToString()); | |
94 WriteLine(Stream, ""); | |
95 } | |
96 | |
97 public static void WriteLine(Stream Stream, string Line) { | |
98 byte[] Buffer = null; | |
99 Buffer = Encoding.ASCII.GetBytes(Line); | |
100 Stream.Write(Buffer, 0, Buffer.Length); | |
101 Stream.WriteByte(13); | |
102 Stream.WriteByte(10); | |
103 } | |
104 } | |
105 | |
106 public abstract class HTTPContent { | |
107 public abstract Result Serve(HTTPContext Context); | |
108 public enum Result : int { | |
109 OK_CLOSE = -2, | |
110 OK_KEEPALIVE = -1, | |
111 ERR_NOTFOUND = 404 | |
112 } | |
113 } | |
114 | |
115 public class HTTPFileContent : HTTPContent { | |
116 public string Filename { get; private set; } | |
117 public string ContentType { get; private set; } | |
118 | |
119 public HTTPFileContent(string Filename) : this(Filename, "application/octet-stream") { } | |
120 public HTTPFileContent(string Filename, string ContentType) { | |
121 this.Filename = Filename; | |
122 this.ContentType = ContentType; | |
123 } | |
124 | |
125 public override Result Serve(HTTPContext Context) { | |
126 if (!File.Exists(Filename)) return Result.ERR_NOTFOUND; | |
127 | |
128 using (FileStream FileStream = File.OpenRead(Filename)) { | |
129 HTTPServer.SendHeader(Context.Stream, 200, ContentType, (int)FileStream.Length); | |
130 byte[] Buffer = new byte[1025]; | |
131 while (FileStream.CanRead) { | |
132 int Length = FileStream.Read(Buffer, 0, Buffer.Length); | |
133 if (Length <= 0) break; | |
134 Context.Stream.Write(Buffer, 0, Length); | |
135 } | |
136 } | |
137 return Result.OK_CLOSE; | |
138 } | |
139 } | |
140 | |
141 public class HTTPContext { | |
142 public HTTPRequest Request { get; internal set; } | |
143 public TCPStream Stream { get; internal set; } | |
144 } | |
145 | |
146 public enum Method { | |
147 GET = 0, | |
148 HEAD = 1, | |
149 POST = 2, | |
150 PUT = 3 | |
151 } | |
152 | |
153 public class HTTPRequest { | |
154 public HTTP.Method Method { get; internal set; } | |
155 public string Path { get; internal set; } | |
156 public string Query { get; internal set; } | |
157 } | |
158 } |