1 /*
2  * Geario - A cross-platform abstraction library with asynchronous I/O.
3  *
4  * Copyright (C) 2021-2022 Kerisy.com
5  *
6  * Website: https://www.kerisy.com
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module http.HttpServer;
13 
14 import geario.buffer.Bytes;
15 
16 import geario.event;
17 import geario.logging;
18 
19 import geario.net.TcpListener;
20 import geario.net.TcpStream;
21 
22 import geario.codec.Framed;
23 
24 import http.codec.HttpCodec;
25 
26 import http.HttpRequest;
27 import http.HttpResponse;
28 
29 class HttpServer
30 {
31     private
32     {
33         TcpListener _listener;
34         EventLoop _loop;
35     }
36 
37     this()
38     {
39         _loop = new EventLoop();
40         _listener = new TcpListener(_loop);
41     }
42 
43     void Listen(ushort port)
44     {
45         _listener.Bind(port);
46         _listener.Accepted((TcpListener sender, TcpStream connection) {
47             log.info("new connection from: %s", connection.RemoteAddress.toString());
48 
49             auto codec = new HttpCodec();
50             auto framed = codec.CreateFramed(connection);
51 
52             framed.OnFrame((HttpRequest request)
53                 {
54                     log.trace("content: %s", request.content);
55                     HttpResponse response = new HttpResponse();
56                     string path = request.uri;
57                     if(path == "/plaintext")
58                     {
59                         response.headers["Content-Type"] = ["text/plain"];
60                         response.content = cast(ubyte[])"Hello, World!".dup;
61                     }
62 
63                     framed.Send(response);
64                 });
65 
66             connection.Disconnected(() {
67                     log.info("client disconnected: %s", connection.RemoteAddress.toString());
68                 }).Closed(() {
69                     log.info("connection closed, local: %s, remote: %s",
70                         connection.LocalAddress.toString(), connection.RemoteAddress.toString());
71                 }).Error((IoError error) { 
72                     log.error("Error occurred: %d  %s", error.errorCode, error.errorMsg); 
73                 });
74         });
75     }
76 
77     void Start()
78     {
79         log.trace("Listening on: %s", _listener.BindingAddress.toString());
80 
81         _listener.Start();
82         _loop.Run();
83     }
84 }