public IAsyncResult BeginProcessRequest(HttpContextBase context, AsyncCallback callback, object state) { var tcs = new TaskCompletionSource<Action>(state); if (callback != null) tcs.Task.ContinueWith(task => callback(task), TaskContinuationOptions.ExecuteSynchronously); var request = context.Request; var response = context.Response; var pathBase = request.ApplicationPath; if (pathBase == "/" || pathBase == null) pathBase = ""; if (_root != null) pathBase += _root; var path = request.Path; if (path.StartsWith(pathBase)) path = path.Substring(pathBase.Length); var serverVarsToAddToEnv = request.ServerVariables.AllKeys .Where(key => !key.StartsWith("HTTP_") && !string.Equals(key, "ALL_HTTP") && !string.Equals(key, "ALL_RAW")) .Select(key => new KeyValuePair<string, object>(key, request.ServerVariables.Get(key))); var env = new Dictionary<string, object>(); env[OwinConstants.Version] = "1.0"; env[OwinConstants.RequestMethod] = request.HttpMethod; env[OwinConstants.RequestScheme] = request.Url.Scheme; env[OwinConstants.RequestPathBase] = pathBase; env[OwinConstants.RequestPath] = path; env[OwinConstants.RequestQueryString] = request.ServerVariables["QUERY_STRING"]; env[OwinConstants.RequestProtocol] = request.ServerVariables["SERVER_PROTOCOL"]; env["aspnet.HttpContextBase"] = context; env[OwinConstants.CallCompleted] = tcs.Task; #if ASPNET_WEBSOCKETS if (context.IsWebSocketRequest) env[OwinConstants.WebSocketSupport] = "WebSocketFunc"; #endif foreach (var kv in serverVarsToAddToEnv) env["server." + kv.Key] = kv.Value; var requestHeaders = request.Headers.AllKeys .ToDictionary(x => x, x => request.Headers.GetValues(x), StringComparer.OrdinalIgnoreCase); var requestStream = request.InputStream; try { _app.Invoke(env, requestHeaders, requestStream) .ContinueWith(taskResultParameters => { if (taskResultParameters.IsFaulted) { tcs.TrySetException(taskResultParameters.Exception.InnerExceptions); } else if (taskResultParameters.IsCanceled) { tcs.TrySetCanceled(); } else { try { var resultParameters = taskResultParameters.Result; var properties = resultParameters.Item1; var responseStatus = resultParameters.Item2; var responseHeader = resultParameters.Item3; var responseCopyTo = resultParameters.Item4; response.BufferOutput = false; response.StatusCode = responseStatus; object reasonPhrase; if (properties.TryGetValue(OwinConstants.ReasonPhrase, out reasonPhrase)) response.StatusDescription = Convert.ToString(reasonPhrase); if (responseHeader != null) { foreach (var header in responseHeader) { foreach (var headerValue in header.Value) response.AddHeader(header.Key, headerValue); } } #if ASPNET_WEBSOCKETS object tempWsBodyDelegate; if (responseStatus == 101 && properties.TryGetValue(OwinConstants.WebSocketBodyDelegte, out tempWsBodyDelegate) && tempWsBodyDelegate != null) { var wsBodyDelegate = (WebSocketAction)tempWsBodyDelegate; context.AcceptWebSocketRequest(async websocketContext => { env["aspnet.AspNetWebSocketContext"] = websocketContext; var webSocket = websocketContext.WebSocket; await wsBodyDelegate(WebSocketSendAsync(webSocket), WebSocketReceiveAsync(webSocket), WebSocketCloseAsync(webSocket)); switch (webSocket.State) { case WebSocketState.Closed: // closed gracefully, no action needed case WebSocketState.Aborted: // closed abortively, no action needed break; case WebSocketState.CloseReceived: await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); break; case WebSocketState.Open: case WebSocketState.CloseSent: // No close received, abort so we don't have to drain the pipe. websocketContext.WebSocket.Abort(); break; default: throw new ArgumentOutOfRangeException("state", webSocket.State, string.Empty); } if (responseCopyTo != null) await responseCopyTo(response.OutputStream); response.Close(); }); tcs.TrySetResult(() => { }); } else #endif if (responseCopyTo != null) { responseCopyTo(response.OutputStream) .ContinueWith(taskCopyTo => { if (taskResultParameters.IsFaulted) tcs.TrySetException(taskResultParameters.Exception.InnerExceptions); else if (taskResultParameters.IsCanceled) tcs.TrySetCanceled(); else tcs.TrySetResult(() => { }); }); } else { // if you reach here it means you didn't implmement AppAction correctly // tcs.TrySetResult(() => { }); } } catch (Exception ex) { tcs.TrySetException(ex); } } }); } catch (Exception ex) { tcs.TrySetException(ex); } return tcs.Task; }