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 }