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 }