public static AppFunc Middleware(AppFunc app) { return env => { var request = new OwinRequest(env); var websocketVersion = request.Get<string>(OwinConstants.WebSocket.Version); WebSocketAccept webSocketAccept = request.Get<WebSocketAccept>(OwinConstants.WebSocket.Accept); if (request.CanUpgrade && websocketVersion == null) // If we have opaque support and no WebSocket support yet { if (IsWebSocketRequest(env)) { // TODO: check for correct requested version of WebSocket protocol IDictionary<string, object> acceptOptions = null; WebSocketFunc webSocketFunc = null; // Announce websocket support env[OwinConstants.WebSocket.Accept] = new WebSocketAccept( (options, callback) => { acceptOptions = options; webSocketFunc = callback; env[OwinConstants.ResponseStatusCode] = 101; }); return app(env).ContinueWith(t => { OwinResponse response = new OwinResponse(env); if (response.StatusCode == 101 && webSocketFunc != null) { SetWebSocketResponseHeaders(env, acceptOptions); request.UpgradeDelegate(acceptOptions, opaqueEnv => { WebSocketLayer webSocket = new WebSocketLayer(opaqueEnv); return webSocketFunc(webSocket.Environment) .ContinueWith(tt => webSocket.CleanupAsync()); }); } }); } } // else return app(env); }; }
private async Task<Http2ServerSession> CreateUpgradeSessionAsync(OwinRequest owinRequest) { // Create a new Http2Session object with the following: // A reference to AppFunc _next // Client cert (if any) // Stream with ID 1 containing request headers & properties copied from the current environment, queued for dispatch to _next AppFunc once upgrade is complete. // Misc extra keys? local & remote IPAddress & ports, IsLocal, capabilities, (not send-file? might still work with careful flushing) X509Certificate clientCert = null; if (string.Equals(owinRequest.Scheme, "https", StringComparison.OrdinalIgnoreCase)) { Func<Task> loadCertAsync = owinRequest.Get<Func<Task>>("ssl.LoadClientCert"); if (loadCertAsync != null) { await loadCertAsync(); } clientCert = owinRequest.Get<X509Certificate>("ssl.ClientCertificate"); } // The opaque stream and CancellationToken will be provided after the opaque upgrade. return new Http2ServerSession(_nextHttp2, CreateTransportInfo(clientCert, owinRequest), CopyHandshakeRequest(owinRequest)); }