/// <summary>
        /// Configures the application to forward incoming requests to a local Single Page
        /// Application (SPA) development server. This is only intended to be used during
        /// development. Do not enable this middleware in production applications.
        /// </summary>
        /// <param name="spaBuilder">The <see cref="IMulitSpaBuilder"/>.</param>
        /// <param name="baseUriTaskFactory">A callback that will be invoked on each request to supply a <see cref="Task"/> that resolves with the target base URI to which requests should be proxied.</param>
        public static void UseProxyToSpaDevelopmentServer(
            this IMulitSpaBuilder spaBuilder,
            Func <Task <Uri> > baseUriTaskFactory)
        {
            var applicationBuilder       = spaBuilder.ApplicationBuilder;
            var applicationStoppingToken = GetStoppingToken(applicationBuilder);

            // Since we might want to proxy WebSockets requests (e.g., by default, AngularCliMiddleware
            // requires it), enable it for the app
            applicationBuilder.UseWebSockets();

            // It's important not to time out the requests, as some of them might be to
            // server-sent event endpoints or similar, where it's expected that the response
            // takes an unlimited time and never actually completes
            var neverTimeOutHttpClient =
                SpaProxy.CreateHttpClientForProxy(Timeout.InfiniteTimeSpan);

            // Proxy all requests to the SPA development server
            applicationBuilder.Use(async(context, next) =>
            {
                if (context.Request.Path.StartsWithSegments(PathString.FromUriComponent(spaBuilder.Options.PublicPath)))
                {
                    var didProxyRequest = await SpaProxy.PerformProxyRequest(
                        context, neverTimeOutHttpClient, baseUriTaskFactory(), applicationStoppingToken,
                        proxy404s: true);
                }
                else
                {
                    await next();
                }
            });
        }
        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path.StartsWithSegments(_pathPrefix) || _pathPrefixIsRoot)
            {
                var didProxyRequest = await SpaProxy.PerformProxyRequest(
                    context, _httpClient, _baseUriTask, _applicationStoppingToken, proxy404s : false);

                if (didProxyRequest)
                {
                    return;
                }
            }

            // Not a request we can proxy
            await _next.Invoke(context);
        }
        public ConditionalProxyMiddleware(
            RequestDelegate next,
            string pathPrefix,
            TimeSpan requestTimeout,
            Task <Uri> baseUriTask,
            IHostApplicationLifetime applicationLifetime)
        {
            if (!pathPrefix.StartsWith("/"))
            {
                pathPrefix = "/" + pathPrefix;
            }

            _next                     = next;
            _pathPrefix               = pathPrefix;
            _pathPrefixIsRoot         = string.Equals(_pathPrefix, "/", StringComparison.Ordinal);
            _baseUriTask              = baseUriTask;
            _httpClient               = SpaProxy.CreateHttpClientForProxy(requestTimeout);
            _applicationStoppingToken = applicationLifetime.ApplicationStopping;
        }