From 814441c9336d4bdd7b29c4b4bd7deaf7492d7277 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 2 Jan 2018 14:13:47 +0000 Subject: [PATCH] Allow configuration of SPA startup timeout. Part of #1447 --- .../AngularCli/AngularCliMiddleware.cs | 6 +++--- .../Prerendering/SpaPrerenderingExtensions.cs | 7 +++---- .../ReactDevelopmentServerMiddleware.cs | 6 +++--- .../SpaOptions.cs | 6 ++++++ 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.AspNetCore.SpaServices.Extensions/AngularCli/AngularCliMiddleware.cs b/src/Microsoft.AspNetCore.SpaServices.Extensions/AngularCli/AngularCliMiddleware.cs index c6aa54c..fe13b4a 100644 --- a/src/Microsoft.AspNetCore.SpaServices.Extensions/AngularCli/AngularCliMiddleware.cs +++ b/src/Microsoft.AspNetCore.SpaServices.Extensions/AngularCli/AngularCliMiddleware.cs @@ -20,7 +20,6 @@ namespace Microsoft.AspNetCore.SpaServices.AngularCli { private const string LogCategoryName = "Microsoft.AspNetCore.SpaServices"; private static TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(5); // This is a development-time only feature, so a very long timeout is fine - private static TimeSpan StartupTimeout = TimeSpan.FromSeconds(50); // Note that the HTTP request itself by default times out after 60s, so you only get useful error information if this is shorter public static void Attach( ISpaBuilder spaBuilder, @@ -54,9 +53,10 @@ namespace Microsoft.AspNetCore.SpaServices.AngularCli { // On each request, we create a separate startup task with its own timeout. That way, even if // the first request times out, subsequent requests could still work. - return targetUriTask.WithTimeout(StartupTimeout, + var timeout = spaBuilder.Options.StartupTimeout; + return targetUriTask.WithTimeout(timeout, $"The Angular CLI process did not start listening for requests " + - $"within the timeout period of {StartupTimeout.Seconds} seconds. " + + $"within the timeout period of {timeout.Seconds} seconds. " + $"Check the log output for error information."); }); } diff --git a/src/Microsoft.AspNetCore.SpaServices.Extensions/Prerendering/SpaPrerenderingExtensions.cs b/src/Microsoft.AspNetCore.SpaServices.Extensions/Prerendering/SpaPrerenderingExtensions.cs index ec41090..b791b3a 100644 --- a/src/Microsoft.AspNetCore.SpaServices.Extensions/Prerendering/SpaPrerenderingExtensions.cs +++ b/src/Microsoft.AspNetCore.SpaServices.Extensions/Prerendering/SpaPrerenderingExtensions.cs @@ -24,8 +24,6 @@ namespace Microsoft.AspNetCore.Builder /// public static class SpaPrerenderingExtensions { - private static TimeSpan BuildTimeout = TimeSpan.FromSeconds(50); // Note that the HTTP request itself by default times out after 60s, so you only get useful error information if this is shorter - /// /// Enables server-side prerendering middleware for a Single Page Application. /// @@ -71,6 +69,7 @@ namespace Microsoft.AspNetCore.Builder var excludePathStrings = (options.ExcludeUrls ?? Array.Empty()) .Select(url => new PathString(url)) .ToArray(); + var buildTimeout = spaBuilder.Options.StartupTimeout; applicationBuilder.Use(async (context, next) => { @@ -93,9 +92,9 @@ namespace Microsoft.AspNetCore.Builder // For better debuggability, create a per-request timeout that makes it clear if the // prerendering builder took too long for this request, but without aborting the // underlying build task so that subsequent requests could still work. - await buildOnDemandTask.WithTimeout(BuildTimeout, + await buildOnDemandTask.WithTimeout(buildTimeout, $"The prerendering build process did not complete within the " + - $"timeout period of {BuildTimeout.Seconds} seconds. " + + $"timeout period of {buildTimeout.Seconds} seconds. " + $"Check the log output for error information."); } diff --git a/src/Microsoft.AspNetCore.SpaServices.Extensions/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs b/src/Microsoft.AspNetCore.SpaServices.Extensions/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs index 146a648..78a7b4f 100644 --- a/src/Microsoft.AspNetCore.SpaServices.Extensions/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs +++ b/src/Microsoft.AspNetCore.SpaServices.Extensions/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs @@ -19,7 +19,6 @@ namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer { private const string LogCategoryName = "Microsoft.AspNetCore.SpaServices"; private static TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(5); // This is a development-time only feature, so a very long timeout is fine - private static TimeSpan StartupTimeout = TimeSpan.FromSeconds(50); // Note that the HTTP request itself by default times out after 60s, so you only get useful error information if this is shorter public static void Attach( ISpaBuilder spaBuilder, @@ -53,9 +52,10 @@ namespace Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer { // On each request, we create a separate startup task with its own timeout. That way, even if // the first request times out, subsequent requests could still work. - return targetUriTask.WithTimeout(StartupTimeout, + var timeout = spaBuilder.Options.StartupTimeout; + return targetUriTask.WithTimeout(timeout, $"The create-react-app server did not start listening for requests " + - $"within the timeout period of {StartupTimeout.Seconds} seconds. " + + $"within the timeout period of {timeout.Seconds} seconds. " + $"Check the log output for error information."); }); } diff --git a/src/Microsoft.AspNetCore.SpaServices.Extensions/SpaOptions.cs b/src/Microsoft.AspNetCore.SpaServices.Extensions/SpaOptions.cs index a562b87..912c290 100644 --- a/src/Microsoft.AspNetCore.SpaServices.Extensions/SpaOptions.cs +++ b/src/Microsoft.AspNetCore.SpaServices.Extensions/SpaOptions.cs @@ -67,5 +67,11 @@ namespace Microsoft.AspNetCore.SpaServices /// development. The directory may not exist in published applications. /// public string SourcePath { get; set; } + + /// + /// Gets or sets the maximum duration that a request will wait for the SPA + /// to become ready to serve to the client. + /// + public TimeSpan StartupTimeout { get; set; } = TimeSpan.FromSeconds(50); } }