1 module hunt.http.HttpConnection; 2 3 import hunt.http.HttpConnection; 4 import hunt.http.HttpOptions; 5 import hunt.http.HttpVersion; 6 7 import hunt.io.ByteBuffer; 8 import hunt.concurrency.ScheduledThreadPoolExecutor; 9 import hunt.Exceptions; 10 import hunt.Functions; 11 import hunt.logging; 12 import hunt.net.AbstractConnection; 13 import hunt.net.Connection; 14 import hunt.net.Exceptions; 15 import hunt.net.secure.SecureSession; 16 import hunt.util.Common; 17 18 import std.exception; 19 import std.socket; 20 21 /** 22 * 23 */ 24 enum HttpConnectionType { 25 HTTP1, HTTP2, HTTP_TUNNEL, WEB_SOCKET 26 } 27 28 interface HttpConnection : Closeable { // : Connection 29 30 enum string NAME = typeof(this).stringof; 31 32 int getId(); 33 34 Connection getTcpConnection(); 35 36 HttpVersion getHttpVersion(); 37 38 Address getLocalAddress(); 39 40 Address getRemoteAddress(); 41 42 HttpConnection onClose(Action1!(HttpConnection) handler); 43 44 HttpConnection onException(Action2!(HttpConnection, Exception) handler); 45 46 47 /** 48 * Returns the value of the user-defined attribute of this connection. 49 * 50 * @param key the key of the attribute 51 * @return <tt>null</tt> if there is no attribute with the specified key 52 */ 53 Object getAttribute(string key); 54 55 /** 56 * Sets a user-defined attribute. 57 * 58 * @param key the key of the attribute 59 * @param value the value of the attribute 60 */ 61 void setAttribute(string key, Object value); 62 63 /** 64 * Removes a user-defined attribute with the specified key. 65 * 66 * @param key The key of the attribute we want to remove 67 * @return The old value of the attribute. <tt>null</tt> if not found. 68 */ 69 Object removeAttribute(string key); 70 71 /** 72 * @param key The key of the attribute we are looking for in the connection 73 * @return <tt>true</tt> if this connection contains the attribute with 74 * the specified <tt>key</tt>. 75 */ 76 bool containsAttribute(string key); 77 } 78 79 80 /** 81 * 82 */ 83 abstract class AbstractHttpConnection : HttpConnection { 84 85 protected ScheduledThreadPoolExecutor executor; 86 87 protected Connection _tcpSession; 88 protected HttpVersion _httpVersion; 89 // protected ConnectionEvent!HttpConnection connectionEvent; 90 protected Action1!HttpConnection _closeHandler; 91 protected Action2!(HttpConnection, Exception) _exceptionHandler; 92 93 this(Connection tcpSession, HttpVersion httpVersion) { 94 this._tcpSession = tcpSession; 95 this._httpVersion = httpVersion; 96 // connectionEvent = new ConnectionEvent!(HttpConnection)(this); 97 } 98 99 // alias tcpSession this ; 100 Connection getTcpConnection() { 101 return _tcpSession; 102 } 103 104 abstract HttpConnectionType getConnectionType(); 105 106 107 Address getLocalAddress() { 108 return _tcpSession.getLocalAddress(); 109 } 110 111 Address getRemoteAddress() { 112 return _tcpSession.getRemoteAddress(); 113 } 114 115 override HttpVersion getHttpVersion() { 116 return _httpVersion; 117 } 118 119 int getId() { 120 return _tcpSession.getId(); 121 } 122 123 bool isSecured() { 124 return _tcpSession.isSecured(); 125 } 126 127 void setAttribute(string key, Object value) { 128 _tcpSession.setAttribute(key, value); 129 } 130 131 Object getAttribute(string key) { 132 return _tcpSession.getAttribute(key); 133 } 134 135 Object removeAttribute(string key) { 136 return _tcpSession.removeAttribute(key); 137 } 138 139 bool containsAttribute(string key) { 140 return _tcpSession.containsAttribute(key); 141 } 142 143 override 144 HttpConnection onClose(Action1!HttpConnection handler) { 145 _closeHandler = handler; 146 return this; 147 // return connectionEvent.onClose(closedListener); 148 } 149 150 override 151 HttpConnection onException(Action2!(HttpConnection, Exception) handler) { 152 _exceptionHandler = handler; 153 return this; 154 // return connectionEvent.onException(exceptionListener); 155 } 156 157 void notifyClose() { 158 // implementationMissing(false); 159 // connectionEvent.notifyClose(); 160 if(_closeHandler !is null) { 161 _closeHandler(this); 162 } 163 } 164 165 void notifyException(Exception t) { 166 // implementationMissing(false); 167 if(_exceptionHandler !is null) { 168 _exceptionHandler(this, t); 169 } 170 // connectionEvent.notifyException(t); 171 } 172 173 /// 174 void close() { 175 _tcpSession.close(); 176 } 177 178 179 180 // ByteBuffer decrypt(ByteBuffer buffer) { 181 182 // implementationMissing(false); 183 // return null; 184 185 // // if (isEncrypted()) { 186 // // try { 187 // // return secureSession.read(buffer); 188 // // } catch (IOException e) { 189 // // throw new SecureNetException("decrypt exception", e); 190 // // } 191 // // } else { 192 // // return null; 193 // // } 194 // } 195 196 // void encrypt(ByteBufferOutputEntry entry) { 197 // implementationMissing(false); 198 // // encrypt!(ByteBuffer)(entry, (buffers, callback) { 199 // // try { 200 // // secureSession.write(buffers, callback); 201 // // } catch (IOException e) { 202 // // throw new SecureNetException("encrypt exception", e); 203 // // } 204 // // }); 205 // } 206 207 // void encrypt(ByteBufferArrayOutputEntry entry) { 208 // encrypt(entry, (buffers, callback) { 209 // try { 210 // secureSession.write(buffers, callback); 211 // } catch (IOException e) { 212 // throw new SecureNetException("encrypt exception", e); 213 // } 214 // }); 215 // } 216 217 // void encrypt(ByteBuffer buffer) { 218 // // try { 219 // // secureSession.write(buffer, Callback.NOOP); 220 // // } catch (IOException e) { 221 // // errorf(e.toString()); 222 // // throw new SecureNetException("encrypt exception", e); 223 // // } 224 225 // implementationMissing(false); 226 // } 227 228 // void encrypt(ByteBuffer[] buffers) { 229 // // try { 230 // // secureSession.write(buffers, Callback.NOOP); 231 // // } catch (IOException e) { 232 // // throw new SecureNetException("encrypt exception", e); 233 // // } 234 // implementationMissing(false); 235 // } 236 237 // private void encrypt(T)(OutputEntry!T entry, Action2!(T, Callback) et) { 238 239 // implementationMissing(false); 240 // // if (isEncrypted()) { 241 // // et(entry.getData(), entry.getCallback()); 242 // // } 243 // } 244 245 } 246 247 248 /** 249 * 250 */ 251 abstract class HttpConnectionHandler : NetConnectionHandlerAdapter { 252 253 // override 254 // DataHandleStatus messageReceived(Connection connection, Object message) { 255 // implementationMissing(false); 256 // return DataHandleStatus.Done; 257 // } 258 259 override 260 void exceptionCaught(Connection connection, Throwable t) { 261 try { 262 version(HUNT_DEBUG) warningf("HTTP handler exception: %s", t.toString()); 263 if(connection is null) { 264 version(HUNT_DEBUG) warning("Connection is null."); 265 } else { 266 Object attachment = connection.getAttribute(HttpConnection.NAME); 267 if (attachment is null) { 268 version(HUNT_DEBUG) warningf("attachment is null"); 269 } else { 270 AbstractHttpConnection httpConnection = cast(AbstractHttpConnection) attachment; 271 if (httpConnection !is null ) { 272 Exception ex = cast(Exception)t; 273 if(ex is null && t !is null) { 274 warningf("Can't handle a exception. Exception: %s", t.msg); 275 } 276 httpConnection.notifyException(ex); 277 } 278 } 279 } 280 } finally { 281 if(connection !is null) 282 connection.close(); 283 } 284 } 285 286 override 287 void connectionClosed(Connection connection) { 288 version(HUNT_DEBUG) { 289 infof("Connection %d closed event. Remote host: %s", 290 connection.getId(), connection.getRemoteAddress()); 291 } 292 293 Object attachment = connection.getAttribute(HttpConnection.NAME); 294 if (attachment is null) { 295 version(HUNT_HTTP_DEBUG) warningf("no connection attached"); 296 } else { 297 version(HUNT_HTTP_DEBUG) tracef("attached connection: %s", typeid(attachment).name); 298 AbstractHttpConnection httpConnection = cast(AbstractHttpConnection) attachment; 299 if (httpConnection !is null) { 300 try { 301 httpConnection.notifyClose(); 302 } catch (Exception e) { 303 errorf("The http connection close exception", e); 304 } 305 } 306 } 307 } 308 309 // override 310 // void connectionOpened(Connection connection) { 311 // implementationMissing(false); 312 // } 313 314 // override 315 // void failedOpeningConnection(int connectionId, Throwable t) { 316 // errorf("Failed to open a http connection %d, reason: <%s>", connectionId, t.msg); 317 // super.failedOpeningConnection(connectionId, t); 318 // } 319 320 override 321 void failedAcceptingConnection(int connectionId, Throwable t) { implementationMissing(false); } 322 }