diff --git a/README.md b/README.md
index 8ea9f71..56a93fb 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,17 @@ dotnet serve -o
dotnet serve -o -S
```
+... with a specific port (otherwise, it defaults to a random, unused port).
+```
+dotnet serve --port 8080
+```
+
+... with access allowed to remote machines (defaults to loopback only.) Use this if running inside Docker.
+
+```
+dotnet serve --address any
+```
+
## Usage
```
@@ -45,7 +56,10 @@ Options:
-d|--directory
The root directory to serve. [Current directory]
-o|--open-browser Open a web browser when the server starts. [false]
-p|--port Port to use [8080]. Use 0 for a dynamic port.
- -a|--address Address to use [127.0.0.1]
+ -a|--address Address to use. [Default = localhost].
+ Accepts IP addresses,
+ 'localhost' for only accept requests from loopback connections, or
+ 'any' to accept requests from any IP address.
--path-base The base URL path of postpended to the site url.
--reverse-proxy Map a path pattern to another url.
Expected format is =.
diff --git a/src/dotnet-serve/CommandLineOptions.cs b/src/dotnet-serve/CommandLineOptions.cs
index d705d7d..fa9836f 100644
--- a/src/dotnet-serve/CommandLineOptions.cs
+++ b/src/dotnet-serve/CommandLineOptions.cs
@@ -30,7 +30,7 @@ internal class CommandLineOptions
[Range(0, 65535, ErrorMessage = "Invalid port. Ports must be in the range of 0 to 65535.")]
public int? Port { get; internal set; }
- [Option("-a|--address ", Description = "Address to use [127.0.0.1]")]
+ [Option("-a|--address ", Description = "Address to use. [Default = localhost].\nAccepts IP addresses,\n'localhost' for only accept requests from loopback connections, or\n'any' to accept requests from any IP address.")]
public IPAddress[] Addresses { get; }
[Option("--path-base ", Description = "The base URL path of postpended to the site url.")]
diff --git a/src/dotnet-serve/IPAddressParser.cs b/src/dotnet-serve/IPAddressParser.cs
index 59fb976..377095e 100644
--- a/src/dotnet-serve/IPAddressParser.cs
+++ b/src/dotnet-serve/IPAddressParser.cs
@@ -18,6 +18,11 @@ public IPAddress Parse(string argName, string value, CultureInfo culture)
return IPAddress.Loopback;
}
+ if (string.Equals("any", value, StringComparison.OrdinalIgnoreCase))
+ {
+ return IPAddress.IPv6Any;
+ }
+
if (!IPAddress.TryParse(value, out var address))
{
throw new FormatException($"'{value}' is not a valid IP address");
diff --git a/src/dotnet-serve/SimpleServer.cs b/src/dotnet-serve/SimpleServer.cs
index db1ebd2..22f3080 100644
--- a/src/dotnet-serve/SimpleServer.cs
+++ b/src/dotnet-serve/SimpleServer.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
+using System.Net;
using System.Runtime.InteropServices;
using McMaster.Extensions.CommandLineUtils;
using Microsoft.AspNetCore.Hosting;
@@ -80,7 +81,14 @@ void ConfigureHttps(ListenOptions options)
{
foreach (var a in _options.Addresses)
{
- o.Listen(a, port.GetValueOrDefault(), ConfigureHttps);
+ if (a == IPAddress.IPv6Any)
+ {
+ o.ListenAnyIP(port.GetValueOrDefault(), ConfigureHttps);
+ }
+ else
+ {
+ o.Listen(a, port.GetValueOrDefault(), ConfigureHttps);
+ }
}
}
})
@@ -103,12 +111,13 @@ void ConfigureHttps(ListenOptions options)
}
await host.StartAsync(cancellationToken);
- AfterServerStart(host);
+ var logger = host.Services.GetRequiredService>();
+ AfterServerStart(host, logger);
await host.WaitForShutdownAsync(cancellationToken);
return 0;
}
- private void AfterServerStart(IWebHost host)
+ private void AfterServerStart(IWebHost host, ILogger logger)
{
var addresses = host.ServerFeatures.Get();
var pathBase = _options.GetPathBase();
@@ -116,6 +125,7 @@ private void AfterServerStart(IWebHost host)
_console.WriteLine(GetListeningAddressText(addresses));
foreach (var a in addresses.Addresses)
{
+ logger.LogDebug("Listening on {address}", a);
_console.WriteLine(ConsoleColor.Green, " " + NormalizeToLoopbackAddress(a) + pathBase);
}
@@ -158,7 +168,7 @@ static string NormalizeToLoopbackAddress(string url)
}
}
- private static void LaunchBrowser(string url)
+ private void LaunchBrowser(string url)
{
var psi = new ProcessStartInfo();
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
@@ -171,13 +181,18 @@ private static void LaunchBrowser(string url)
psi.FileName = "xdg-open";
psi.ArgumentList.Add(url);
}
- else
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
psi.FileName = "cmd";
psi.ArgumentList.Add("/C");
psi.ArgumentList.Add("start");
psi.ArgumentList.Add(url);
}
+ else
+ {
+ _console.Write(ConsoleColor.Red, "Could not determine how to launch the browser for this OS platform.");
+ return;
+ }
Process.Start(psi);
}