1 module hunt.http.server.HttpServer;
2 
3 import hunt.http.server.Http1ServerDecoder;
4 import hunt.http.server.Http2ServerDecoder;
5 import hunt.http.server.HttpServerHandler;
6 import hunt.http.server.Http2ServerRequestHandler;
7 import hunt.http.server.ServerHttpHandler;
8 import hunt.http.server.ServerSessionListener;
9 import hunt.http.server.WebSocketHandler;
10 
11 import hunt.http.codec.CommonDecoder;
12 import hunt.http.codec.CommonEncoder;
13 import hunt.http.codec.http.stream.Http2Configuration;
14 import hunt.http.codec.websocket.decode.WebSocketDecoder;
15 
16 import hunt.container.ByteBuffer;
17 import hunt.event.EventLoop;
18 import hunt.datetime;
19 import hunt.lang.exception;
20 import hunt.logging;
21 import hunt.net;
22 import hunt.util.Lifecycle;
23 
24 import core.time;
25 
26 /**
27 */
28 class HttpServer : AbstractLifecycle {
29 
30     private AbstractServer _server;
31     private HttpServerHandler httpServerHandler;
32     private Http2Configuration http2Configuration;
33     private string host;
34     private int port;
35 
36     this(string host, int port, Http2Configuration http2Configuration,
37             ServerHttpHandler serverHttpHandler) {
38         this(host, port, http2Configuration, new Http2ServerRequestHandler(serverHttpHandler),
39                 serverHttpHandler, new WebSocketHandler());
40     }
41 
42     this(string host, int port, Http2Configuration http2Configuration,
43             ServerHttpHandler serverHttpHandler, WebSocketHandler webSocketHandler) {
44         this(host, port, http2Configuration, new Http2ServerRequestHandler(serverHttpHandler),
45                 serverHttpHandler, webSocketHandler);
46     }
47 
48     this(string host, int port, Http2Configuration c, ServerSessionListener listener,
49             ServerHttpHandler serverHttpHandler, WebSocketHandler webSocketHandler) {
50         if (c is null)
51             throw new IllegalArgumentException("the http2 configuration is null");
52 
53         if (host is null)
54             throw new IllegalArgumentException("the http2 server host is empty");
55 
56         this.host = host;
57         this.port = port;
58         httpServerHandler = new HttpServerHandler(c, listener,
59                 serverHttpHandler, webSocketHandler);
60 
61         Http1ServerDecoder httpServerDecoder = new Http1ServerDecoder(new WebSocketDecoder(),
62                 new Http2ServerDecoder());
63         CommonDecoder commonDecoder = new CommonDecoder(httpServerDecoder);
64         c.getTcpConfiguration().setDecoder(commonDecoder);
65         c.getTcpConfiguration().setEncoder(new CommonEncoder());
66         c.getTcpConfiguration().setHandler(httpServerHandler);
67 
68         _server = NetUtil.createNetServer!(ServerThreadMode.Single)();
69         _server.setConfig(c.getTcpConfiguration());
70 
71         //         string responseString = `HTTP/1.1 000 
72         // Server: Hunt-HTTP/1.0
73         // Date: Tue, 11 Dec 2018 08:17:36 GMT
74         // Content-Type: text/plain
75         // Content-Length: 13
76         // Connection: keep-alive
77 
78         // Hello, World!`;
79 
80         _server.connectionHandler((NetSocket sock) {
81             version (HUNT_DEBUG)
82                 infof("new http session with %s", sock.remoteAddress);
83             AsynchronousTcpSession session = cast(AsynchronousTcpSession) sock;
84             session.handler((const ubyte[] data) {
85                 version (HUNT_METRIC) {
86                     debug trace("start hadling session data ...");
87                     MonoTime startTime = MonoTime.currTime;
88                 } else version (HUNT_DEBUG) {
89                     trace("start hadling session data ...");
90                 }
91                 ByteBuffer buf = ByteBuffer.wrap(cast(byte[]) data);
92                 commonDecoder.decode(buf, session);
93 
94                 version (HUNT_METRIC) {
95                     Duration timeElapsed = MonoTime.currTime - startTime;
96                     warningf("handling done for session %d in: %d microseconds",
97                     session.getSessionId, timeElapsed.total!(TimeUnit.Microsecond)());
98                     tracef("session handling done: %s.", session.toString());
99                 } else version (HUNT_DEBUG)
100                     tracef("session handling done");
101 
102                 // session.write(responseString, () {
103                 // version(HUNT_METRIC) {
104                 //     Duration timeElapsed = MonoTime.currTime - startTime;
105                 //     warningf("handling done for session %d in: %d microseconds",
106                 //         session.getSessionId, timeElapsed.total!(TimeUnit.Microsecond)());
107                 //     debug tracef("session handling done: %s.", session.toString());
108                 // }                      
109                 // });
110             });
111         });
112         this.http2Configuration = c;
113 
114         version (HUNT_DEBUG) {
115             if (c.isSecureConnectionEnabled)
116                 tracef("Listing at: https://%s:%d", host, port);
117             else
118                 tracef("Listing at: http://%s:%d", host, port);
119         }
120     }
121 
122     Http2Configuration getHttp2Configuration() {
123         return http2Configuration;
124     }
125 
126     string getHost() {
127         return host;
128     }
129 
130     int getPort() {
131         return port;
132     }
133 
134     // ExecutorService getNetExecutorService() {
135     //     return _server.getNetExecutorService();
136     // }
137 
138     override protected void initialize() {
139         _server.listen(host, port);
140     }
141 
142     override protected void destroy() {
143         if (_server !is null) {
144             _server.stop();
145         }
146     }
147 
148 }