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 }