1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
| using System.Net;
namespace Mirage {
using Handler = Func<Context, Task>;
using Middleware = Func<Context, Func<Context, Task>, Task>;
public class Server {
public enum HttpMethod {
Get,
Post,
};
private readonly HttpListener listener;
private readonly List<Middleware> middlewares;
private readonly Dictionary<string, Dictionary<HttpMethod, Handler>> router;
public Server() {
listener = new HttpListener();
middlewares = new List<Middleware>();
router = new Dictionary<string, Dictionary<HttpMethod, Handler>>();
}
public Server AddPrefix(string prefix) {
listener.Prefixes.Add(prefix);
return this;
}
public Server AddMiddleware(Middleware middleware) {
middlewares.Add(middleware);
return this;
}
public Server DefineRoute(string path, HttpMethod method, Handler handler) {
if (!router.ContainsKey(path)) {
router.Add(path, new Dictionary<HttpMethod, Handler>());
}
router[path][method] = handler;
return this;
}
public Server DefineGet(string path, Handler handler) {
return DefineRoute(path, HttpMethod.Get, handler);
}
public Server DefinePost(string path, Handler handler) {
return DefineRoute(path, HttpMethod.Post, handler);
}
public async Task Run(CancellationToken token) {
listener.Start();
while (!token.IsCancellationRequested) {
var context = new Context(
await listener.GetContextAsync()
);
try {
await RouteRequest(context);
} catch (Exception e) {
await context.Result(e.ToString());
}
}
listener.Stop();
}
public Task Run() {
return Run(CancellationToken.None);
}
private async Task RouteRequest(Context context) {
var path = context.Request.Url?.AbsolutePath ?? "/";
var method = ParseHttpMethod(context.Request.HttpMethod);
if (!router.ContainsKey(path)) {
throw new Exception("route not found");
}
var route = router[path];
if (!route.ContainsKey(method)) {
throw new Exception("method is not suported");
}
var handler = route[method];
await CallMiddlewareChain(context, middlewares);
await handler.Invoke(context);
}
private Task CallMiddlewareChain(Context context, IEnumerable<Middleware> middlewares) {
var middleware = middlewares.FirstOrDefault();
if (middleware == null) {
return Task.CompletedTask;
}
return middleware.Invoke(
context,
ctx => CallMiddlewareChain(ctx, middlewares.Skip(1))
);
}
private HttpMethod ParseHttpMethod(string method) {
switch (method.ToLower()) {
case "get":
return HttpMethod.Get;
case "post":
return HttpMethod.Post;
default:
throw new Exception("unknown method");
}
}
}
}
|