├── CONTRIBUTING.md
├── NuGet.config
├── dotnet-serve.sln.licenseheader
├── Directory.Build.targets
├── .vscode
├── tasks.json
└── launch.json
├── .gitignore
├── src
└── dotnet-serve
│ ├── dotnet-serve.csproj
│ ├── IPAddressAttribute.cs
│ ├── Program.cs
│ └── SimpleServer.cs
├── CHANGELOG.md
├── .appveyor.yml
├── version.props
├── .gitattributes
├── Directory.Build.props
├── README.md
├── dotnet-serve.sln
├── .editorconfig
└── LICENSE.txt
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing
2 | ============
3 |
4 | A few simple rules for the road.
5 |
6 | 1. Before opening a PR with a significant change, open an issue so we can discuss design issues.
7 | 1. Play nice.
8 |
--------------------------------------------------------------------------------
/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/dotnet-serve.sln.licenseheader:
--------------------------------------------------------------------------------
1 | extensions: designer.cs generated.cs
2 | extensions: .cs
3 | // Copyright (c) Nate McMaster.
4 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
5 |
--------------------------------------------------------------------------------
/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "build",
6 | "group": {
7 | "kind": "build",
8 | "isDefault": true
9 | },
10 | "command": "dotnet",
11 | "type": "process",
12 | "args": [
13 | "build",
14 | "--no-restore",
15 | "${workspaceFolder}/src/dotnet-serve/dotnet-serve.csproj"
16 | ],
17 | "problemMatcher": "$msCompile"
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | [Oo]bj/
2 | [Bb]in/
3 | TestResults/
4 | .nuget/
5 | .build/
6 | .testPublish/
7 | *.sln.ide/
8 | _ReSharper.*/
9 | packages/
10 | artifacts/
11 | PublishProfiles/
12 | .vs/
13 | bower_components/
14 | node_modules/
15 | **/wwwroot/lib/
16 | debugSettings.json
17 | project.lock.json
18 | *.user
19 | *.suo
20 | *.cache
21 | *.docstates
22 | _ReSharper.*
23 | *.exe
24 | *.psess
25 | *.vsp
26 | *.pidb
27 | *.userprefs
28 | *DS_Store
29 | *.ncrunchsolution
30 | *.*sdf
31 | *.ipch
32 | .settings
33 | *.sln.ide
34 | node_modules/
35 | **/[Cc]ompiler/[Rr]esources/**/*.js
36 | .idea/
37 | *.iml
38 | launchSettings.json
39 |
40 |
--------------------------------------------------------------------------------
/src/dotnet-serve/dotnet-serve.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.1
6 | true
7 | true
8 | dotnet-serve
9 | A simple command-line HTTP server.
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": ".NET Core Launch (console)",
6 | "type": "coreclr",
7 | "request": "launch",
8 | "preLaunchTask": "build",
9 | "program": "${workspaceFolder}/.build/bin/dotnet-serve/Debug/netcoreapp2.1/dotnet-serve.dll",
10 | "args": [],
11 | "cwd": "${workspaceFolder}/src/dotnet-serve",
12 | "console": "internalConsole",
13 | "stopAtEntry": false,
14 | "internalConsoleOptions": "openOnSessionStart"
15 | },
16 | {
17 | "name": ".NET Core Attach",
18 | "type": "coreclr",
19 | "request": "attach",
20 | "processId": "${command:pickProcess}"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/src/dotnet-serve/IPAddressAttribute.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Nate McMaster.
2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3 |
4 | using System.ComponentModel.DataAnnotations;
5 | using System.Net;
6 |
7 | namespace McMaster.DotNet.Server
8 | {
9 | sealed class IPAddressAttribute : ValidationAttribute
10 | {
11 | protected override ValidationResult IsValid(object value, ValidationContext context)
12 | {
13 | if (value is string str && !IPAddress.TryParse(str, out _))
14 | {
15 | return new ValidationResult($"'{value}' is not a valid IP address");
16 | }
17 |
18 | return ValidationResult.Success;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [Unreleased]
4 |
5 | Enhancements:
6 | - Add `--path-base` option to support setting a root URL to postpend to the site URL
7 |
8 | Fixes:
9 | - Launch the browser to localhost when 0.0.0.0 or [::] is used
10 |
11 | ## [v0.2.0]
12 |
13 | **March 13, 2018**
14 |
15 | Initial release of dotnet-serve as a global CLI tool.
16 |
17 | Changes:
18 | - Release the package as a DotnetTool package (global CLI tool)
19 | - Drop support for installing as a DotNetCliToolReference
20 | - Update to ASP.NET Core 2.1.0-preview1-final
21 |
22 | ## [v0.1.0]
23 | Initial release
24 | - Provides a simple command-line web server for dotnet
25 |
26 | [Unreleased]: https://github.com/natemcmaster/dotnet-serve/compare/v0.2.0...HEAD
27 | [v0.2.0]: https://github.com/natemcmaster/dotnet-serve/compare/v0.1.0...v0.2.0
28 | [v0.1.0]: https://github.com/natemcmaster/dotnet-serve/tree/v0.1.0
29 |
30 |
--------------------------------------------------------------------------------
/src/dotnet-serve/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Nate McMaster.
2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3 |
4 | using System;
5 | using System.Threading.Tasks;
6 | using McMaster.Extensions.CommandLineUtils;
7 |
8 | namespace McMaster.DotNet.Server
9 | {
10 | class Program
11 | {
12 | // Return codes
13 | private const int ERROR = 2;
14 | private const int OK = 0;
15 |
16 | public static async Task Main(string[] args)
17 | {
18 | try
19 | {
20 | return await CommandLineApplication.ExecuteAsync(args);
21 | }
22 | catch (Exception ex)
23 | {
24 | Console.ForegroundColor = ConsoleColor.Red;
25 | Console.Error.WriteLine("Unexpected error: " + ex.ToString());
26 | Console.ResetColor();
27 | return ERROR;
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/.appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 0.2.1-alpha.{build}
2 | install:
3 | - ps: iwr https://raw.githubusercontent.com/dotnet/cli/release/2.1.3xx/scripts/obtain/dotnet-install.ps1 -outfile dotnet-install.ps1
4 | - ps: .\dotnet-install.ps1 -Version 2.1.300-preview1-008174 -InstallDir $env:ProgramFiles/dotnet
5 | branches:
6 | only:
7 | - master
8 | - appveyor
9 | - /^feature\/.*/
10 | build_script:
11 | - ps: .\build.ps1 -IsOfficialBuild
12 | environment:
13 | global:
14 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
15 | DOTNET_CLI_TELEMETRY_OPTOUT: 1
16 | test: off
17 | os: Visual Studio 2017
18 | artifacts:
19 | - path: 'artifacts\*.nupkg'
20 | name: Packages
21 | type: NuGetPackages
22 | deploy:
23 | - provider: NuGet
24 | name: myget
25 | artifact: Packages
26 | server: https://www.myget.org/F/natemcmaster/api/v2/package
27 | symbol_server: https://www.myget.org/F/natemcmaster/api/v2/package
28 | api_key:
29 | secure: KF1yGk4IHJyyfiHfFSCxJ+p5iZX+KPfCTnCihjD5iIZjasTS1lHeilpbaon4wvcM
30 |
--------------------------------------------------------------------------------
/version.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 0.2.1
4 | alpha
5 | $(VersionPrefix)-$(VersionSuffix)
6 | $(VersionPrefix)
7 |
8 | $(APPVEYOR_BUILD_NUMBER)
9 | 0
10 | $(VersionPrefix).$(BuildNumber)
11 | $(VersionSuffix).$(BuildNumber)
12 |
13 |
14 |
15 |
16 | <_Parameter1>BuildNumber
17 | <_Parameter2>$(BuildNumber)
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.doc diff=astextplain
2 | *.DOC diff=astextplain
3 | *.docx diff=astextplain
4 | *.DOCX diff=astextplain
5 | *.dot diff=astextplain
6 | *.DOT diff=astextplain
7 | *.pdf diff=astextplain
8 | *.PDF diff=astextplain
9 | *.rtf diff=astextplain
10 | *.RTF diff=astextplain
11 |
12 | *.jpg binary
13 | *.png binary
14 | *.gif binary
15 |
16 | *.cs text=auto diff=csharp
17 | *.vb text=auto
18 | *.resx text=auto
19 | *.c text=auto
20 | *.cpp text=auto
21 | *.cxx text=auto
22 | *.h text=auto
23 | *.hxx text=auto
24 | *.py text=auto
25 | *.rb text=auto
26 | *.java text=auto
27 | *.html text=auto
28 | *.htm text=auto
29 | *.css text=auto
30 | *.scss text=auto
31 | *.sass text=auto
32 | *.less text=auto
33 | *.js text=auto
34 | *.lisp text=auto
35 | *.clj text=auto
36 | *.sql text=auto
37 | *.php text=auto
38 | *.lua text=auto
39 | *.m text=auto
40 | *.asm text=auto
41 | *.erl text=auto
42 | *.fs text=auto
43 | *.fsx text=auto
44 | *.hs text=auto
45 |
46 | *.csproj text=auto
47 | *.vbproj text=auto
48 | *.fsproj text=auto
49 | *.dbproj text=auto
50 | *.sln text=auto eol=crlf
51 |
52 | *.sh eol=lf
53 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Nate McMaster
7 | dotnet-serve
8 | Copyright © Nate McMaster
9 | en-US
10 | false
11 | https://www.apache.org/licenses/LICENSE-2.0
12 | https://github.com/natemcmaster/dotnet-serve
13 | https://github.com/natemcmaster/dotnet-serve.git
14 | See $(PackageProjectUrl)/blob/master/CHANGELOG.md#v$(VersionPrefix.Replace('.','')) for release notes.
15 | git
16 | false
17 | true
18 | 7.1
19 |
20 | $(MSBuildThisFileDirectory)build\StrongName.snk
21 | true
22 | true
23 |
24 | true
25 | true
26 |
27 | $(MSBuildThisFileDirectory).build\obj\$(MSBuildProjectName)
28 | $(MSBuildThisFileDirectory).build\bin\$(MSBuildProjectName)
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | dotnet-serve
2 | ============
3 |
4 | [![AppVeyor build status][appveyor-badge]](https://ci.appveyor.com/project/natemcmaster/dotnet-serve/branch/master)
5 |
6 | [appveyor-badge]: https://img.shields.io/appveyor/ci/natemcmaster/dotnet-serve/master.svg?label=appveyor&style=flat-square
7 |
8 | [![NuGet][main-nuget-badge]][main-nuget] [![MyGet][main-myget-badge]][main-myget]
9 |
10 | [main-nuget]: https://www.nuget.org/packages/dotnet-serve/
11 | [main-nuget-badge]: https://img.shields.io/nuget/v/dotnet-serve.svg?style=flat-square&label=nuget
12 | [main-myget]: https://www.myget.org/feed/natemcmaster/package/nuget/dotnet-serve
13 | [main-myget-badge]: https://img.shields.io/www.myget/natemcmaster/vpre/dotnet-serve.svg?style=flat-square&label=myget
14 |
15 | A simple command-line HTTP server.
16 |
17 | It launches a server in the current working directory and serves all files in it.
18 |
19 | ## Installation
20 |
21 | The latest release of dotnet-serve requires the [2.1.300-preview1](https://www.microsoft.com/net/download/dotnet-core/sdk-2.1.300-preview1) .NET Core SDK or newer.
22 | Once installed, run this command:
23 |
24 | ```
25 | dotnet install tool --global dotnet-serve
26 | ```
27 |
28 | ## Usage
29 |
30 | ```
31 | dotnet serve [path] [options]
32 |
33 | Arguments:
34 | path Base path to the server root. Defaults to the current directory.
35 |
36 | Options:
37 | -p|--port Port to use [8080]. Use 0 for a dynamic port.
38 | -a|--address Address to use [0.0.0.0]
39 | -o|--open-browser Open a web browser when the server starts [false]
40 | -?|-h|--help Show help information
41 | ```
42 |
--------------------------------------------------------------------------------
/dotnet-serve.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio 15
3 | VisualStudioVersion = 15.0.26124.0
4 | MinimumVisualStudioVersion = 15.0.26124.0
5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C769ED8F-FD49-48BF-AE78-1F6ABCEAD42B}"
6 | EndProject
7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-serve", "src\dotnet-serve\dotnet-serve.csproj", "{03156D3A-5F48-4F6B-8DAB-3ACED9241F1D}"
8 | EndProject
9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1BABEE13-E148-472E-955A-1592CF8FC87E}"
10 | ProjectSection(SolutionItems) = preProject
11 | .appveyor.yml = .appveyor.yml
12 | .editorconfig = .editorconfig
13 | .gitattributes = .gitattributes
14 | .gitignore = .gitignore
15 | build.cmd = build.cmd
16 | build.ps1 = build.ps1
17 | CHANGELOG.md = CHANGELOG.md
18 | CONTRIBUTING.md = CONTRIBUTING.md
19 | Directory.Build.props = Directory.Build.props
20 | Directory.Build.targets = Directory.Build.targets
21 | dotnet-serve.sln.licenseheader = dotnet-serve.sln.licenseheader
22 | LICENSE.txt = LICENSE.txt
23 | NuGet.config = NuGet.config
24 | README.md = README.md
25 | version.props = version.props
26 | EndProjectSection
27 | EndProject
28 | Global
29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
30 | Debug|Any CPU = Debug|Any CPU
31 | Release|Any CPU = Release|Any CPU
32 | EndGlobalSection
33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
34 | {03156D3A-5F48-4F6B-8DAB-3ACED9241F1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {03156D3A-5F48-4F6B-8DAB-3ACED9241F1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {03156D3A-5F48-4F6B-8DAB-3ACED9241F1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {03156D3A-5F48-4F6B-8DAB-3ACED9241F1D}.Release|Any CPU.Build.0 = Release|Any CPU
38 | EndGlobalSection
39 | GlobalSection(SolutionProperties) = preSolution
40 | HideSolutionNode = FALSE
41 | EndGlobalSection
42 | GlobalSection(NestedProjects) = preSolution
43 | {03156D3A-5F48-4F6B-8DAB-3ACED9241F1D} = {C769ED8F-FD49-48BF-AE78-1F6ABCEAD42B}
44 | EndGlobalSection
45 | GlobalSection(ExtensibilityGlobals) = postSolution
46 | SolutionGuid = {9E6AF21B-9CC7-414F-8D8F-E12676569DB4}
47 | EndGlobalSection
48 | EndGlobal
49 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | trim_trailing_whitespace = true
6 | insert_final_newline = true
7 |
8 | [*.{xml,csproj,props,targets,config}]
9 | indent_size = 2
10 |
11 | [*.json]
12 | indent_size = 2
13 |
14 | [*.cs]
15 | indent_size = 4
16 |
17 | # Style I care about
18 | csharp_style_expression_bodied_constructors = false : error
19 | csharp_prefer_braces = true : error
20 | dotnet_sort_system_directives_first = true : error
21 |
22 | # Stuff that is usually best
23 | csharp_style_inlined_variable_declaration = true : warning
24 | csharp_style_var_elsewhere = true : warning
25 | csharp_space_after_cast = true : warning
26 | csharp_style_pattern_matching_over_as_with_null_check = true : warning
27 | csharp_style_pattern_matching_over_is_with_cast_check = true : warning
28 | csharp_style_var_for_built_in_types = true : warning
29 | csharp_style_var_when_type_is_apparent = true : warning
30 | csharp_new_line_before_catch = true : warning
31 | csharp_new_line_before_else = true : warning
32 | csharp_new_line_before_finally = true : warning
33 | csharp_indent_case_contents = true : warning
34 | csharp_new_line_before_open_brace = all
35 | csharp_indent_switch_labels = true : warning
36 | csharp_indent_labels = one_less_than_current
37 | csharp_prefer_simple_default_expression = true : warning
38 |
39 | # Good defaults, but not always
40 | dotnet_style_object_initializer = true : suggestion
41 | csharp_style_expression_bodied_indexers = true : suggestion
42 | csharp_style_expression_bodied_accessors = true : suggestion
43 | csharp_style_throw_expression = true : suggestion
44 |
45 | # Naming styles
46 |
47 | ## Constants are PascalCase
48 | dotnet_naming_style.pascal_case.capitalization = pascal_case
49 |
50 | dotnet_naming_symbols.constants.applicable_kinds = *
51 | dotnet_naming_symbols.constants.required_modifiers = const
52 |
53 | dotnet_naming_rule.constants_should_be_pascale_case.symbols = constants
54 | dotnet_naming_rule.constants_should_be_pascale_case.style = pascal_case
55 | dotnet_naming_rule.constants_should_be_pascale_case.severity = error
56 |
57 | ## Private static fields start with s_
58 | dotnet_naming_style.s_underscore_camel_case.required_prefix = s_
59 | dotnet_naming_style.s_underscore_camel_case.capitalization = camel_case
60 |
61 | dotnet_naming_symbols.private_static_fields.applicable_kinds = field
62 | dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private
63 | dotnet_naming_symbols.private_static_fields.required_modifiers = static
64 |
65 | dotnet_naming_rule.private_static_fields_should_be_underscore.symbols = private_static_fields
66 | dotnet_naming_rule.private_static_fields_should_be_underscore.style = s_underscore_camel_case
67 | dotnet_naming_rule.private_static_fields_should_be_underscore.severity = error
68 |
69 | ## Private fields are _camelCase
70 | dotnet_naming_style.underscore_camel_case.required_prefix = _
71 | dotnet_naming_style.underscore_camel_case.capitalization = camel_case
72 |
73 | dotnet_naming_symbols.private_fields.applicable_kinds = field
74 | dotnet_naming_symbols.private_fields.applicable_accessibilities = private
75 |
76 | dotnet_naming_rule.private_fields_should_be_underscore.symbols = private_fields
77 | dotnet_naming_rule.private_fields_should_be_underscore.style = underscore_camel_case
78 | dotnet_naming_rule.private_fields_should_be_underscore.severity = error
79 |
--------------------------------------------------------------------------------
/src/dotnet-serve/SimpleServer.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Nate McMaster.
2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3 |
4 | using System;
5 | using System.ComponentModel.DataAnnotations;
6 | using System.Diagnostics;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Net;
10 | using System.Runtime.InteropServices;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using McMaster.Extensions.CommandLineUtils;
14 | using Microsoft.AspNetCore.Builder;
15 | using Microsoft.AspNetCore.Hosting;
16 | using Microsoft.AspNetCore.Hosting.Server.Features;
17 | using Microsoft.Extensions.Logging;
18 | using IOPath = System.IO.Path;
19 |
20 | namespace McMaster.DotNet.Server
21 | {
22 | [Command(
23 | Name = "dotnet serve",
24 | FullName = "dotnet-serve",
25 | Description = "Provides a simple HTTP server")]
26 | [HelpOption]
27 | class SimpleServer
28 | {
29 | [Argument(0, Name = "path", Description = "Base path to the server root")]
30 | [DirectoryExists]
31 | public string Path { get; }
32 |
33 | [Option(Description = "Port to use [8080]. Use 0 for a dynamic port.")]
34 | [Range(0, 65535, ErrorMessage = "Invalid port. Ports must be in the range of 0 to 65535.")]
35 | public int Port { get; } = 8080;
36 |
37 | [Option(Description = "Address to use [0.0.0.0]")]
38 | [IPAddress]
39 | public string Address { get; } = "0.0.0.0";
40 |
41 | [Option(Description = "Open a web browser when the server starts. [false]")]
42 | public bool OpenBrowser { get; }
43 |
44 | [Option("--path-base ", Description = "The base URL path of postpended to the site url.")]
45 | public string PathBase { get; private set; }
46 |
47 | public async Task OnExecute(IConsole console)
48 | {
49 | var cts = new CancellationTokenSource();
50 | console.CancelKeyPress += (o, e) =>
51 | {
52 | console.WriteLine("Shutting down...");
53 | cts.Cancel();
54 | };
55 |
56 | var address = IPAddress.Parse(Address);
57 | var path = Path != null
58 | ? IOPath.GetFullPath(Path)
59 | : Directory.GetCurrentDirectory();
60 |
61 | if (!string.IsNullOrEmpty(PathBase) && PathBase[0] != '/')
62 | {
63 | PathBase = "/" + PathBase;
64 | }
65 |
66 | var host = new WebHostBuilder()
67 | .ConfigureLogging(l =>
68 | {
69 | l.SetMinimumLevel(LogLevel.Information);
70 | l.AddConsole();
71 | })
72 | .PreferHostingUrls(false)
73 | .UseKestrel(o =>
74 | {
75 | if (IPAddress.Any.Equals(address))
76 | {
77 | o.ListenLocalhost(Port);
78 | o.ListenAnyIP(Port);
79 | }
80 |
81 | o.Listen(address, Port);
82 | })
83 | .UseSockets()
84 | .UseWebRoot(path)
85 | .UseContentRoot(path)
86 | .UseEnvironment("Production")
87 | .Configure(app =>
88 | {
89 | app.UseStatusCodePages("text/html",
90 | "Error {0}HTTP {0}
");
91 |
92 | if (!string.IsNullOrEmpty(PathBase))
93 | {
94 | app.Map(PathBase, Configure);
95 | }
96 | else
97 | {
98 | Configure(app);
99 | }
100 | })
101 | .Build();
102 |
103 | console.ForegroundColor = ConsoleColor.DarkYellow;
104 | console.Write("Starting server, serving ");
105 | console.ResetColor();
106 | console.WriteLine(IOPath.GetRelativePath(Directory.GetCurrentDirectory(), path));
107 |
108 | await host.StartAsync(cts.Token);
109 |
110 | var addresses = host.ServerFeatures.Get();
111 |
112 | console.WriteLine("Listening on:");
113 | console.ForegroundColor = ConsoleColor.Green;
114 | foreach (var a in addresses.Addresses)
115 | {
116 | console.WriteLine(" " + a + PathBase);
117 | }
118 |
119 | console.ResetColor();
120 | console.WriteLine("");
121 | console.WriteLine("Press CTRL+C to exit");
122 |
123 | if (OpenBrowser)
124 | {
125 | var url = addresses.Addresses.First();
126 | // normalize to loopback if binding to IPAny
127 | url = url.Replace("0.0.0.0", "localhost");
128 | url = url.Replace("[::]", "localhost");
129 |
130 | if (!string.IsNullOrEmpty(PathBase))
131 | {
132 | url += PathBase;
133 | }
134 |
135 | LaunchBrowser(url);
136 | }
137 |
138 | await host.WaitForShutdownAsync(cts.Token);
139 | return 0;
140 | }
141 |
142 | private static void Configure(IApplicationBuilder app)
143 | {
144 | app.UseFileServer(new FileServerOptions
145 | {
146 | EnableDefaultFiles = true,
147 | EnableDirectoryBrowsing = true,
148 | StaticFileOptions =
149 | {
150 | ServeUnknownFileTypes = true,
151 | },
152 | });
153 | }
154 |
155 | private static void LaunchBrowser(string url)
156 | {
157 | string processName;
158 | string[] args;
159 | if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
160 | {
161 | processName = "open";
162 | args = new[] { url };
163 | }
164 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
165 | {
166 | processName = "xdg-open";
167 | args = new[] { url };
168 | }
169 | else
170 | {
171 | processName = "cmd";
172 | args = new[] { "/C", "start", url };
173 | }
174 |
175 | Process.Start(processName, ArgumentEscaper.EscapeAndConcatenate(args));
176 | }
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
--------------------------------------------------------------------------------