Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
add optional port parameter to UseReactDevelopmentServer and `UseAn…
…gularCliServer`
  • Loading branch information
stephtr committed Oct 17, 2018
commit 7d2a2b66b507561dd60e67750afd18b9c2816af1
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ internal static class AngularCliMiddleware

public static void Attach(
ISpaBuilder spaBuilder,
string npmScriptName)
string npmScriptName,
int? spaPort)
{
var sourcePath = spaBuilder.Options.SourcePath;
if (string.IsNullOrEmpty(sourcePath))
Expand All @@ -36,10 +37,25 @@ public static void Attach(
throw new ArgumentException("Cannot be null or empty", nameof(npmScriptName));
}

// Start Angular CLI and attach to middleware pipeline
var appBuilder = spaBuilder.ApplicationBuilder;
var logger = LoggerFinder.GetOrCreateLogger(appBuilder, LogCategoryName);
var angularCliServerInfoTask = StartAngularCliServerAsync(sourcePath, npmScriptName, logger);
// We have to start the server by ourself if there wasn't any port specified
// or the specified port is still free (unused).
var shouldStartServer = !spaPort.HasValue || TcpPortFinder.TestPortAvailability(spaPort.Value);

Task<AngularCliServerInfo> angularCliServerInfoTask;
if (shouldStartServer)
{
// Start Angular CLI and attach to middleware pipeline
var appBuilder = spaBuilder.ApplicationBuilder;
var logger = LoggerFinder.GetOrCreateLogger(appBuilder, LogCategoryName);
angularCliServerInfoTask = StartAngularCliServerAsync(sourcePath, npmScriptName, logger);
}
else
{
angularCliServerInfoTask = Task.FromResult(new AngularCliServerInfo
{
Port = spaPort.Value
});
}

// Everything we proxy is hardcoded to target http://localhost because:
// - the requests are always from the local machine (we're not accepting remote
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ public static class AngularCliMiddlewareExtensions
/// </summary>
/// <param name="spaBuilder">The <see cref="ISpaBuilder"/>.</param>
/// <param name="npmScript">The name of the script in your package.json file that launches the Angular CLI process.</param>
/// <param name="spaPort">The port which the create-react-app server should listen to (optional).</param>
public static void UseAngularCliServer(
this ISpaBuilder spaBuilder,
string npmScript)
string npmScript,
int? spaPort = null)
{
if (spaBuilder == null)
{
Expand All @@ -37,7 +39,7 @@ public static void UseAngularCliServer(
throw new InvalidOperationException($"To use {nameof(UseAngularCliServer)}, you must supply a non-empty value for the {nameof(SpaOptions.SourcePath)} property of {nameof(SpaOptions)} when calling {nameof(SpaApplicationBuilderExtensions.UseSpa)}.");
}

AngularCliMiddleware.Attach(spaBuilder, npmScript);
AngularCliMiddleware.Attach(spaBuilder, npmScript, spaPort);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ internal static class ReactDevelopmentServerMiddleware

public static void Attach(
ISpaBuilder spaBuilder,
string npmScriptName)
string npmScriptName,
int? spaPort)
{
var sourcePath = spaBuilder.Options.SourcePath;
if (string.IsNullOrEmpty(sourcePath))
Expand All @@ -35,10 +36,22 @@ public static void Attach(
throw new ArgumentException("Cannot be null or empty", nameof(npmScriptName));
}

// Start create-react-app and attach to middleware pipeline
var appBuilder = spaBuilder.ApplicationBuilder;
var logger = LoggerFinder.GetOrCreateLogger(appBuilder, LogCategoryName);
var portTask = StartCreateReactAppServerAsync(sourcePath, npmScriptName, logger);
// We have to start the server by ourself if there wasn't any port specified
// or the specified port is still free (unused).
var shouldStartServer = !spaPort.HasValue || TcpPortFinder.TestPortAvailability(spaPort.Value);

Task<int> portTask;
if (shouldStartServer)
{
// Start create-react-app and attach to middleware pipeline
var appBuilder = spaBuilder.ApplicationBuilder;
var logger = LoggerFinder.GetOrCreateLogger(appBuilder, LogCategoryName);
portTask = StartCreateReactAppServerAsync(sourcePath, npmScriptName, logger);
}
else
{
portTask = Task.FromResult(spaPort.Value);
}

// Everything we proxy is hardcoded to target http://localhost because:
// - the requests are always from the local machine (we're not accepting remote
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ public static class ReactDevelopmentServerMiddlewareExtensions
/// </summary>
/// <param name="spaBuilder">The <see cref="ISpaBuilder"/>.</param>
/// <param name="npmScript">The name of the script in your package.json file that launches the create-react-app server.</param>
/// <param name="spaPort">The port which the create-react-app server should listen to (optional).</param>
public static void UseReactDevelopmentServer(
this ISpaBuilder spaBuilder,
string npmScript)
string npmScript,
int? spaPort = null)
{
if (spaBuilder == null)
{
Expand All @@ -37,7 +39,7 @@ public static void UseReactDevelopmentServer(
throw new InvalidOperationException($"To use {nameof(UseReactDevelopmentServer)}, you must supply a non-empty value for the {nameof(SpaOptions.SourcePath)} property of {nameof(SpaOptions)} when calling {nameof(SpaApplicationBuilderExtensions.UseSpa)}.");
}

ReactDevelopmentServerMiddleware.Attach(spaBuilder, npmScript);
ReactDevelopmentServerMiddleware.Attach(spaBuilder, npmScript, spaPort);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace Microsoft.AspNetCore.SpaServices.Util
Expand All @@ -21,5 +22,19 @@ public static int FindAvailablePort()
listener.Stop();
}
}

public static bool TestPortAvailability(int port)
{
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
var ipEndPoints = ipProperties.GetActiveTcpListeners();
foreach (var endPoint in ipEndPoints)
{
if (endPoint.Port == port)
{
return false;
}
}
return true;
}
}
}