1 module hunt.http.server.HttpServerHandler;
2 
3 import hunt.http.server.HttpServerOptions;
4 import hunt.http.server.Http1ServerConnection;
5 import hunt.http.server.Http1ServerRequestHandler;
6 import hunt.http.server.Http2ServerConnection;
7 import hunt.http.server.Http2ServerRequestHandler;
8 import hunt.http.server.ServerHttpHandler;
9 import hunt.http.server.ServerSessionListener;
10 import hunt.http.server.WebSocketHandler;
11 
12 import hunt.http.HttpConnection;
13 import hunt.http.HttpOptions;
14 import hunt.http.HttpVersion;
15 
16 import hunt.net.secure.SecureSession;
17 import hunt.net.secure.SecureSessionFactory;
18 import hunt.net.Connection;
19 
20 import hunt.Exceptions;
21 import hunt.logging;
22 import hunt.text.Common;
23 
24 import std.range.primitives;
25 import std.string;
26 
27 /**
28  * 
29  */
30 class HttpServerHandler : HttpConnectionHandler {
31 
32     private ServerSessionListener listener;
33     private ServerHttpHandler serverHttpHandler;
34     private WebSocketHandler webSocketHandler;
35     private HttpServerOptions _options;
36 
37     this(HttpServerOptions options, ServerSessionListener listener,
38             ServerHttpHandler serverHttpHandler, WebSocketHandler webSocketHandler) {
39         _options = options;
40         this.listener = listener;
41         this.serverHttpHandler = serverHttpHandler;
42         this.webSocketHandler = webSocketHandler;
43     }
44 
45     override void connectionOpened(Connection connection) {
46         version(HUNT_HTTP_DEBUG_MORE) tracef("New http connection: %s", typeid(cast(Object) connection));
47 
48         version(WITH_HUNT_SECURITY) {
49             if (_options.isSecureConnectionEnabled()) {
50                 buildSecureSession(connection);
51             } else {
52                 buildNomalSession(connection);
53             }
54         } else {
55             buildNomalSession(connection);
56         }
57 
58         super.connectionOpened(connection);
59     }
60 
61     private void buildNomalSession(Connection connection) {
62 
63         connection.setState(ConnectionState.Opening);
64 
65         version (HUNT_HTTP_DEBUG)
66             infof("Building a new http connection...");
67         string protocol = _options.getProtocol();
68         
69         if (!protocol.empty) {
70             Http1ServerConnection httpConnection = new Http1ServerConnection(_options, connection,
71                     new Http1ServerRequestHandler(serverHttpHandler, _options), listener, webSocketHandler);
72             connection.setAttribute(HttpConnection.NAME, httpConnection);
73             serverHttpHandler.acceptConnection(httpConnection);
74             connection.setState(ConnectionState.Opened);
75         } else {
76             enum string HTTP_1_1 = HttpVersion.HTTP_1_1.asString();
77             enum string HTTP_2 = HttpVersion.HTTP_2.asString();
78             // HttpVersion httpVersion = HttpVersion.fromString(protocol);
79             // if (httpVersion == HttpVersion.Null) {
80             //     string msg = "the protocol " ~ protocol ~ " is not support.";
81             //     warning(msg);
82             //     throw new IllegalArgumentException(msg);
83             // }
84 
85             if (icmp(HTTP_1_1, protocol) == 0) {
86                 Http1ServerConnection httpConnection = new Http1ServerConnection(_options, connection, 
87                         new Http1ServerRequestHandler(serverHttpHandler, _options),
88                         listener, webSocketHandler);
89                 connection.setAttribute(HttpConnection.NAME, httpConnection);
90                 serverHttpHandler.acceptConnection(httpConnection);
91                 connection.setState(ConnectionState.Opened);
92             } else if (icmp(HTTP_2, protocol) == 0) {
93                 Http2ServerConnection httpConnection = new Http2ServerConnection(_options,
94                         connection, listener);
95                 connection.setAttribute(HttpConnection.NAME, httpConnection);
96                 serverHttpHandler.acceptConnection(httpConnection);
97                 connection.setState(ConnectionState.Opened);
98 
99             } else {
100                 string msg = "the protocol " ~ protocol ~ " is not support.";
101                 version (HUNT_HTTP_DEBUG) {
102                     warningf(msg);
103                 }
104                 connection.setState(ConnectionState.Error);
105                 throw new IllegalArgumentException(msg);
106             }
107         }
108     }
109 
110 version(WITH_HUNT_SECURITY) {
111     private void buildSecureSession(Connection connection) {
112 
113         import hunt.net.secure.SecureUtils;
114         connection.setState(ConnectionState.Securing);
115         version(HUNT_HTTP_DEBUG) info("building SecureSession ...");
116 
117         SecureSession secureSession = SecureUtils.createServerSession(connection, (SecureSession sslSession) {
118             connection.setState(ConnectionState.Secured);
119             version (HUNT_DEBUG)
120                 info("Secure connection created...");
121 
122             enum string HTTP_1_1 = HttpVersion.HTTP_1_1.asString();
123             enum string HTTP_2 = HttpVersion.HTTP_2.asString();
124 
125             HttpConnection httpConnection;
126             string protocol = sslSession.getApplicationProtocol();
127             if (protocol.empty)
128                 protocol = _options.getProtocol();
129             if (protocol.empty)
130                 protocol = HTTP_1_1;
131 
132             version (HUNT_HTTP_DEBUG) {
133                 tracef("server connection %s SSL handshake finished. Application protocol: %s",
134                     connection.getId(), protocol);
135             }
136 
137             switch (protocol) {
138             case HTTP_1_1:
139                 httpConnection = new Http1ServerConnection(_options, connection, 
140                     new Http1ServerRequestHandler(serverHttpHandler, _options), 
141                     listener, webSocketHandler);
142                 break;
143 
144             case HTTP_2:
145                 httpConnection = new Http2ServerConnection(_options, connection,listener);
146                 break;
147 
148             default:
149                 throw new IllegalStateException(
150                     "SSL application protocol negotiates failure. The protocol "
151                     ~ protocol ~ " is not supported");
152             }
153 
154             connection.setAttribute(HttpConnection.NAME, cast(Object)httpConnection);
155             version (HUNT_HTTP_DEBUG_MORE) infof("attach http connection: %s", typeid(httpConnection));
156 
157             serverHttpHandler.acceptConnection(httpConnection);
158         });
159 
160         connection.setAttribute(SecureSession.NAME, cast(Object)secureSession);
161     }
162 }
163 }