1 module hunt.http.server.WebSocketHandler; 2 3 import hunt.http.HttpOutputStream; 4 5 import hunt.http.WebSocketFrame; 6 import hunt.http.codec.websocket.stream.IOState; 7 import hunt.http.WebSocketConnection; 8 9 import hunt.http.HttpRequest; 10 import hunt.http.HttpResponse; 11 import hunt.http.WebSocketPolicy; 12 13 import hunt.http.HttpConnection; 14 15 import hunt.logging; 16 import hunt.Functions; 17 18 import std.conv; 19 20 /** 21 * 22 */ 23 interface WebSocketHandler { 24 bool acceptUpgrade(HttpRequest request, HttpResponse response, 25 HttpOutputStream output, HttpConnection connection); 26 27 // deprecated("Using onOpen instead.") 28 // alias onConnect = onOpen; 29 30 void onOpen(WebSocketConnection connection); 31 32 void onClosed(WebSocketConnection connection); 33 34 WebSocketPolicy getWebSocketPolicy(); 35 36 void setWebSocketPolicy(WebSocketPolicy w); 37 38 void onFrame(WebSocketFrame frame, WebSocketConnection connection); 39 40 void onError(Exception t, WebSocketConnection connection); 41 } 42 43 alias HttpEventHandler = Func4!(HttpRequest, HttpResponse, HttpOutputStream, HttpConnection, bool); 44 45 /** 46 * 47 */ 48 abstract class AbstractWebSocketHandler : WebSocketHandler { 49 50 protected WebSocketPolicy defaultWebSocketPolicy; 51 protected WebSocketPolicy _webSocketPolicy; 52 53 private HttpEventHandler _acceptUpgradeHandler; 54 private Action1!(WebSocketConnection) _openHandler; 55 private Action1!(WebSocketConnection) _closeHandler; 56 private Action2!(WebSocketFrame, WebSocketConnection) _frameHandler; 57 private Action2!(Exception, WebSocketConnection) _errorHandler; 58 59 this() { 60 defaultWebSocketPolicy = WebSocketPolicy.newServerPolicy(); 61 } 62 63 WebSocketPolicy getWebSocketPolicy() { 64 if (_webSocketPolicy is null) { 65 return defaultWebSocketPolicy; 66 } else { 67 return _webSocketPolicy; 68 } 69 } 70 71 void setWebSocketPolicy(WebSocketPolicy w) { 72 this._webSocketPolicy = w; 73 } 74 75 bool acceptUpgrade(HttpRequest request, HttpResponse response, 76 HttpOutputStream output, HttpConnection connection) { 77 78 version (HUNT_HTTP_DEBUG) { 79 string path = request.getURI().getPath(); 80 infof("The connection %s will upgrade to WebSocket on path %s", 81 connection.getId(), path); 82 } 83 84 if(_acceptUpgradeHandler !is null) 85 return _acceptUpgradeHandler(request, response, output, connection); 86 87 // no handler 88 return false; 89 } 90 91 void onOpen(WebSocketConnection connection) { 92 version (HUNT_HTTP_DEBUG) trace("Opened a connection with ", connection.getRemoteAddress()); 93 if(_openHandler !is null) 94 _openHandler(connection); 95 } 96 97 void onClosed(WebSocketConnection connection) { 98 version (HUNT_HTTP_DEBUG) tracef("Connection %d closed: ", connection.getId(), connection.getRemoteAddress()); 99 if(_closeHandler !is null) 100 _closeHandler(connection); 101 } 102 103 void onFrame(WebSocketFrame frame, WebSocketConnection connection) { 104 version (HUNT_HTTP_DEBUG) { 105 tracef("The WebSocket connection %s received a frame: %s", 106 connection.getId(), frame.to!string()); 107 } 108 109 if(_frameHandler !is null) 110 _frameHandler(frame, connection); 111 } 112 113 void onError(Exception ex, WebSocketConnection connection) { 114 version(HUNT_DEBUG) warningf("WebSocket error: ", ex.msg); 115 version(HUNT_HTTP_DEBUG) error(ex); 116 if(_errorHandler !is null) 117 _errorHandler(ex, connection); 118 } 119 120 AbstractWebSocketHandler onAcceptUpgrade(HttpEventHandler handler) { 121 _acceptUpgradeHandler = handler; 122 return this; 123 } 124 125 AbstractWebSocketHandler onOpen(Action1!(WebSocketConnection) handler) { 126 _openHandler = handler; 127 return this; 128 } 129 130 AbstractWebSocketHandler onClosed(Action1!(WebSocketConnection) handler) { 131 _closeHandler = handler; 132 return this; 133 } 134 135 AbstractWebSocketHandler onFrame(Action2!(WebSocketFrame, WebSocketConnection) handler) { 136 _frameHandler = handler; 137 return this; 138 } 139 140 AbstractWebSocketHandler onError(Action2!(Exception, WebSocketConnection) handler) { 141 _errorHandler = handler; 142 return this; 143 } 144 } 145 146 147 class WebSocketHandlerAdapter : AbstractWebSocketHandler { 148 149 }