/// <summary>
        /// Returns a handler for incoming Web stream requests.
        /// </summary>
        /// <param name="route">
        /// The handler.
        /// </param>
        /// <param name="controller">
        /// The controller.
        /// </param>
        /// <param name="args">
        /// The request parameters.
        /// </param>
        /// <returns>
        /// A handler for incoming Web stream requests.
        /// </returns>
        public static Func <IDictionary <string, object>, Task> WebSocketRequestHandler(
            this ControllerRoute route,
            object controller,
            IDictionary <string, string> args)
        {
            return(async environment =>
            {
                using (var socket = new WebSocket(environment))
                {
                    Task incomingMessagePump;
                    Func <string, IObservable <string> > getObservable;
                    if (route.ObservableParameters != null)
                    {
                        // Route has observable parameters.
                        var observableParams = route.ObservableParameters.ToDictionary(_ => _, _ => new SingleSubscriptionObservable());
                        getObservable = name => observableParams[name].Observable;
                        incomingMessagePump = IncomingMessagePump(socket, observableParams);
                    }
                    else
                    {
                        // No observable parameters.
                        getObservable = _ => Observable.Empty <string>();
                        incomingMessagePump = Task.FromResult(0);
                    }

                    // Hook up the incoming and outgoing message pumps.
                    var outgoing = GetObservableFromHandler(() => route.Invoke(controller, args, getObservable));
                    var outgoingMessagePump = OutgoingMessagePump(outgoing, socket);

                    // Close the socket when both pumps finish.
                    await Task.WhenAll(outgoingMessagePump, incomingMessagePump);
                }
            });
        }
        /// <summary>
        /// Returns an HTTP request handler for single-return routes.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <param name="controller">The controller.</param>
        /// <param name="args">The route arguments.</param>
        /// <returns>An HTTP request handler for single-return routes.</returns>
        private static Func <IOwinContext, Task> GetIdiomaticHttpRequestHandler(ControllerRoute route, object controller, IDictionary <string, string> args)
        {
            return(async environment =>
            {
                var response = environment.Response;
                int code;
                string body;
                try
                {
                    body = await route.Invoke(controller, args, _ => Observable.Empty <string>()).FirstAsync();

                    code = 200;
                }
                catch (Exception e)
                {
                    body = e.ToString();
                    code = 500;
                }

                response.StatusCode = code;
                response.ContentType = "application/json";
                await response.WriteAsync(body);
            });
        }
        /// <summary>
        /// Returns an HTTP request handler for single-return routes.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <param name="controller">The controller.</param>
        /// <param name="args">The route arguments.</param>
        /// <returns>An HTTP request handler for single-return routes.</returns>
        private static Func<IOwinContext, Task> GetIdiomaticHttpRequestHandler(ControllerRoute route, object controller, IDictionary<string, string> args)
        {
            return async environment =>
            {
                var response = environment.Response;
                int code;
                string body;
                try
                {
                    body = await route.Invoke(controller, args, _ => Observable.Empty<string>()).FirstAsync();
                    code = 200;
                }
                catch (Exception e)
                {
                    body = e.ToString();
                    code = 500;
                }

                response.StatusCode = code;
                response.ContentType = "application/json";
                await response.WriteAsync(body);
            };
        }
        /// <summary>
        /// Returns a handler for incoming Web stream requests.
        /// </summary>
        /// <param name="route">
        /// The handler.
        /// </param>
        /// <param name="controller">
        /// The controller.
        /// </param>
        /// <param name="args">
        /// The request parameters.
        /// </param>
        /// <param name="environment">
        /// The environment.
        /// </param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// A handler for incoming Web stream requests.
        /// </returns>
        public static async Task HttpRequestHandler(
            this ControllerRoute route,
            object controller,
            IDictionary <string, string> args,
            IOwinContext environment,
            CancellationToken cancellationToken)
        {
            var response = environment.Response;
            var pump     = new MutuallyExclusiveTaskExecutor();
            var outgoing =
                GetObservableFromHandler(() => route.Invoke(controller, args, _ => Observable.Empty <string>()));

            var headersWritten = new[] { false };

            response.Headers.Set("Transfer-Encoding", "Chunked");
            response.ContentType = "application/json";

            // Hook up the outgoing message pump to the response body.
            var subscription = outgoing.Subscribe(
                msg => pump.Schedule(
                    async() =>
            {
                try
                {
                    if (!headersWritten[0])
                    {
                        headersWritten[0] = true;

                        // Set the response headers.
                        response.StatusCode = 200;
                    }

                    await response.WriteAsync(msg, cancellationToken);
                    await response.Body.FlushAsync(cancellationToken);
                }
                catch
                {
                    pump.Complete();
                    throw;
                }
            }),
                e => pump.Schedule(
                    async() =>
            {
                try
                {
                    if (!headersWritten[0])
                    {
                        // Set the response headers.
                        response.StatusCode = 500;
                        headersWritten[0]   = true;
                    }

                    await response.WriteAsync(e.ToString(), cancellationToken);
                    await response.Body.FlushAsync(cancellationToken);
                }
                finally
                {
                    pump.Complete();
                }
            }),
                () => pump.Schedule(
                    () =>
            {
                if (!headersWritten[0])
                {
                    // No content.
                    response.StatusCode = 204;
                    response.Body.Close();
                    response.Body     = Stream.Null;
                    headersWritten[0] = true;
                }

                pump.Complete();
                return(Task.FromResult(0));
            }));

            // When the cancellation token is cancelled, unsubscribe.
            cancellationToken.Register(subscription.Dispose);
            try
            {
                await pump.Run(cancellationToken);
            }
            finally
            {
                subscription.Dispose();
            }
        }