public async Task <HealthCheckStatus> Check()
        {
            var now = DateTimeOffset.Now;

            if (_lastStatus == null || (_cacheFailures && _lastStatus.HasFailed) || _lastChecked + _cacheTime < now)
            {
                _lastStatus = await _healthCheck.Check().ConfigureAwait(false);

                _lastChecked = now;
                return(_lastStatus);
            }

            return(_lastStatus);
        }
        public override async Task <HealthCheckStatus> Check()
        {
            var request = (HttpWebRequest)WebRequest.Create(_uri);

            request.UserAgent   = "Owin.HealthCheck";
            request.Method      = "GET";
            request.Credentials = _credentials;

            using (var response = (HttpWebResponse)await request.GetResponseAsync().ConfigureAwait(false))
            {
                var statusCode = (int)response.StatusCode;
                if (statusCode >= 200 && statusCode < 300)
                {
                    return(HealthCheckStatus.Passed(response.StatusDescription));
                }
                else
                {
                    return(HealthCheckStatus.Failed(response.StatusDescription));
                }
            }
        }
        public override async Task Invoke(IOwinContext context)
        {
            // Make sure this is an absolute path.
            if (!string.IsNullOrEmpty(context.Request.Path.Value))
            {
                await Next.Invoke(context);

                return;
            }

            var queryParameters = context.Request.GetQueryParameters();
            var debug           = false;

            if (queryParameters.ContainsKey("debug"))
            {
                bool.TryParse(queryParameters["debug"], out debug);
            }

            var checkTasks = _healthChecks.Select(async x =>
            {
                try
                {
                    return(new
                    {
                        Name = x.Name,
                        Status = await x.Check().ConfigureAwait(false)
                    });
                }
                catch (Exception e)
                {
                    return(new
                    {
                        Name = x.Name,
                        Status = HealthCheckStatus.Failed(e.Message)
                    });
                }
            });

            var allTasks = Task.WhenAll(checkTasks.ToArray());

            if (allTasks != await Task.WhenAny(allTasks, Task.Delay(_timeout)).ConfigureAwait(false))
            {
                context.Response.StatusCode = (int)HttpStatusCode.GatewayTimeout;
            }
            else
            {
                var results   = allTasks.Result;
                var hasFailed = results.Any(x => x.Status.HasFailed);
                context.Response.StatusCode = hasFailed ? (int)HttpStatusCode.ServiceUnavailable : (int)HttpStatusCode.OK;

                if (debug)
                {
                    var sb = new StringBuilder();
                    foreach (var r in results)
                    {
                        sb.AppendLine(r.Name + ": " + r.Status.Message);
                    }
                    await context.Response.WriteAsync(sb.ToString());
                }
            }
        }