diff --git a/aspnetcore/fundamentals/servers/httpsys.md b/aspnetcore/fundamentals/servers/httpsys.md index 8bcd1adbd6cf..fbcd65b1764b 100644 --- a/aspnetcore/fundamentals/servers/httpsys.md +++ b/aspnetcore/fundamentals/servers/httpsys.md @@ -1,10 +1,11 @@ --- title: HTTP.sys web server implementation in ASP.NET Core -author: rick-anderson -description: Introduces HTTP.sys, a web server for ASP.NET Core on Windows. Built on the Http.Sys kernel mode driver, HTTP.sys is an alternative to Kestrel that can be used for direct connection to the Internet without IIS. +author: tdykstra +description: Learn about HTTP.sys, a web server for ASP.NET Core on Windows. Built on the HTTP.sys kernel-mode driver, HTTP.sys is an alternative to Kestrel that can be used for direct connection to the Internet without IIS. manager: wpickett -ms.author: riande -ms.date: 08/07/2017 +ms.author: tdykstra +ms.custom: mvc +ms.date: 02/28/2018 ms.prod: asp.net-core ms.technology: aspnet ms.topic: article @@ -12,168 +13,157 @@ uid: fundamentals/servers/httpsys --- # HTTP.sys web server implementation in ASP.NET Core -By [Tom Dykstra](https://github.com/tdykstra) and [Chris Ross](https://github.com/Tratcher) +By [Tom Dykstra](https://github.com/tdykstra), [Chris Ross](https://github.com/Tratcher), and [Luke Latham](https://github.com/guardrex) > [!NOTE] -> This topic applies only to ASP.NET Core 2.0 and later. In earlier versions of ASP.NET Core, HTTP.sys is named [WebListener](xref:fundamentals/servers/weblistener). +> This topic applies to ASP.NET Core 2.0 or later. In earlier versions of ASP.NET Core, HTTP.sys is named [WebListener](xref:fundamentals/servers/weblistener). -HTTP.sys is a [web server for ASP.NET Core](index.md) that runs only on Windows. It's built on the [Http.Sys kernel mode driver](https://msdn.microsoft.com/library/windows/desktop/aa364510.aspx). HTTP.sys is an alternative to [Kestrel](kestrel.md) that offers some features that Kestel doesn't. **HTTP.sys can't be used with IIS or IIS Express, as it's incompatible with the [ASP.NET Core Module](aspnet-core-module.md).** +[HTTP.sys](/iis/get-started/introduction-to-iis/introduction-to-iis-architecture#hypertext-transfer-protocol-stack-httpsys) is a [web server for ASP.NET Core](xref:fundamentals/servers/index) that only runs on Windows. HTTP.sys is an alternative to [Kestrel](xref:fundamentals/servers/kestrel) and offers some features that Kestrel doesn't provide. + +> [!IMPORTANT] +> HTTP.sys is incompatible with the [ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module) and can't be used with IIS or IIS Express. HTTP.sys supports the following features: -- [Windows Authentication](xref:security/authentication/windowsauth) -- Port sharing -- HTTPS with SNI -- HTTP/2 over TLS (Windows 10) -- Direct file transmission -- Response caching -- WebSockets (Windows 8) +* [Windows Authentication](xref:security/authentication/windowsauth) +* Port sharing +* HTTPS with SNI +* HTTP/2 over TLS (Windows 10 or later) +* Direct file transmission +* Response caching +* WebSockets (Windows 8 or later) Supported Windows versions: -- Windows 7 and Windows Server 2008 R2 and later +* Windows 7 or later +* Windows Server 2008 R2 or later [View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/fundamentals/servers/httpsys/sample) ([how to download](xref:tutorials/index#how-to-download-a-sample)) ## When to use HTTP.sys -HTTP.sys is useful for deployments where you need to expose the server directly to the Internet without using IIS. - -![HTTP.sys communicates directly with the Internet](httpsys/_static/httpsys-to-internet.png) - -Because it's built on Http.Sys, HTTP.sys doesn't require a reverse proxy server for protection against attacks. Http.Sys is mature technology that protects against many kinds of attacks and provides the robustness, security, and scalability of a full-featured web server. IIS itself runs as an HTTP listener on top of Http.Sys. - -HTTP.sys is a good choice for internal deployments when you need a feature not available in Kestrel, such as Windows authentication. - -![HTTP.sys communicates directly with your internal network](httpsys/_static/httpsys-to-internal.png) - -## How to use HTTP.sys - -Here's an overview of setup tasks for the host OS and your ASP.NET Core application. - -### Configure Windows Server - -* Install the version of .NET that your application requires, such as [.NET Core](https://www.microsoft.com/net/download/core) or [.NET Framework](https://www.microsoft.com/net/download/framework). - -* Preregister URL prefixes to bind to HTTP.sys, and set up SSL certificates - - If you don't preregister URL prefixes in Windows, you have to run your application with administrator privileges. The only exception is if you bind to localhost using HTTP (not HTTPS) with a port number greater than 1024; in that case, administrator privileges aren't required. - - For details, see [How to preregister prefixes and configure SSL](#preregister-url-prefixes-and-configure-ssl) later in this article. - -* Open firewall ports to allow traffic to reach HTTP.sys. +HTTP.sys is useful for deployments where: - You can use *netsh.exe* or [PowerShell cmdlets](https://technet.microsoft.com/library/jj554906). +* There's a need to expose the server directly to the Internet without using IIS. -There are also [Http.Sys registry settings](https://support.microsoft.com/kb/820129). + ![HTTP.sys communicates directly with the Internet](httpsys/_static/httpsys-to-internet.png) -### Configure your ASP.NET Core application to use HTTP.sys +* An internal deployment requires a feature not available in Kestrel, such as [Windows Authentication](xref:security/authentication/windowsauth). -* No package install is needed if you use the [Microsoft.AspNetCore.All](xref:fundamentals/metapackage) metapackage. The [Microsoft.AspNetCore.Server.HttpSys](https://www.nuget.org/packages/Microsoft.AspNetCore.Server.HttpSys/) package is included in the metapackage. + ![HTTP.sys communicates directly with the internal network](httpsys/_static/httpsys-to-internal.png) -* Call the `UseHttpSys` extension method on `WebHostBuilder` in your `Main` method, specifying any [HTTP.sys options](https://github.com/aspnet/HttpSysServer/blob/rel/2.0.0/src/Microsoft.AspNetCore.Server.HttpSys/HttpSysOptions.cs) that you need, as shown in the following example: +HTTP.sys is mature technology that protects against many types of attacks and provides the robustness, security, and scalability of a full-featured web server. IIS itself runs as an HTTP listener on top of HTTP.sys. - [!code-csharp[](httpsys/sample/Program.cs?name=snippet_Main&highlight=11-19)] - -### Configure HTTP.sys options - -Here are some of the HTTP.sys settings and limits that you can configure. +## How to use HTTP.sys -**Maximum client connections** +### Configure the ASP.NET Core app to use HTTP.sys -The maximum number of concurrent open TCP connections can be set for the entire application with the following code in *Program.cs*: +1. A package reference in the project file isn't required when using the [Microsoft.AspNetCore.All metapackage](xref:fundamentals/metapackage) ([nuget.org](https://www.nuget.org/packages/Microsoft.AspNetCore.All/)) (ASP.NET Core 2.0 or later). When not using the `Microsoft.AspNetCore.All` metapackage, add a package reference to [Microsoft.AspNetCore.Server.HttpSys](https://www.nuget.org/packages/Microsoft.AspNetCore.Server.HttpSys/). -[!code-csharp[](httpsys/sample/Program.cs?name=snippet_Options&highlight=5)] +1. Call the [UseHttpSys](/dotnet/api/microsoft.aspnetcore.hosting.webhostbuilderhttpsysextensions.usehttpsys) extension method when building the web host, specifying any required [HTTP.sys options](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions): -The maximum number of connections is unlimited (null) by default. + [!code-csharp[](httpsys/sample/Program.cs?name=snippet1&highlight=4-12)] -**Maximum request body size** + Additional HTTP.sys configuration is handled through [registry settings](https://support.microsoft.com/kb/820129). -The default maximum request body size is 30,000,000 bytes, which is approximately 28.6MB. + **HTTP.sys options** -The recommended way to override the limit in an ASP.NET Core MVC app is to use the [RequestSizeLimit](https://github.com/aspnet/Mvc/blob/rel/2.0.0/src/Microsoft.AspNetCore.Mvc.Core/RequestSizeLimitAttribute.cs) attribute on an action method: + | Property | Description | Default | + | -------- | ----------- | :-----: | + | [AllowSynchronousIO](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.allowsynchronousio) | Control whether synchronous input/output is allowed for the `HttpContext.Request.Body` and `HttpContext.Response.Body`. | `true` | + | [Authentication.AllowAnonymous](/dotnet/api/microsoft.aspnetcore.server.httpsys.authenticationmanager.allowanonymous) | Allow anonymous requests. | `true` | + | [Authentication.Schemes](/dotnet/api/microsoft.aspnetcore.server.httpsys.authenticationmanager.schemes) | Specify the allowed authentication schemes. May be modified at any time prior to disposing the listener. Values are provided by the [AuthenticationSchemes enum](/dotnet/api/microsoft.aspnetcore.server.httpsys.authenticationschemes): `Basic`, `Kerberos`, `Negotiate`, `None`, and `NTLM`. | `None` | + | [EnableResponseCaching](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.enableresponsecaching) | Attempt [kernel-mode](/windows-hardware/drivers/gettingstarted/user-mode-and-kernel-mode) caching for responses with eligible headers. The response may not include `Set-Cookie`, `Vary`, or `Pragma` headers. It must include a `Cache-Control` header that's `public` and either a `shared-max-age` or `max-age` value, or an `Expires` header. | `true` | + | [MaxAccepts](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.maxaccepts) | The maximum number of concurrent accepts. | 5 × [Environment.
ProcessorCount](/dotnet/api/system.environment.processorcount) | + | [MaxConnections](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.maxconnections) | The maximum number of concurrent connections to accept. Use `-1` for infinite. Use `null` to use the registry's machine-wide setting. | `null`
(unlimited) | + | [MaxRequestBodySize](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.maxrequestbodysize) | See the MaxRequestBodySize section. | 30000000 bytes
(~28.6 MB) | + | [RequestQueueLimit](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.requestqueuelimit) | The maximum number of requests that can be queued. | 1000 | + | [ThrowWriteExceptions](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.throwwriteexceptions) | Indicate if response body writes that fail due to client disconnects should throw exceptions or complete normally. | `false`
(complete normally) | + | [Timeouts](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.timeouts) | Expose the HTTP.sys [TimeoutManager](/dotnet/api/microsoft.aspnetcore.server.httpsys.timeoutmanager) configuration, which may also be configured in the registry. Follow the API links to learn more about each setting, including default values: | | + | [UrlPrefixes](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.urlprefixes) | Specify the [UrlPrefixCollection](/dotnet/api/microsoft.aspnetcore.server.httpsys.urlprefixcollection) to register with HTTP.sys. The most useful is [UrlPrefixCollection.Add](/dotnet/api/microsoft.aspnetcore.server.httpsys.urlprefixcollection.add), which is used to add a prefix to the collection. These may be modified at any time prior to disposing the listener. | | -```csharp -[RequestSizeLimit(100000000)] -public IActionResult MyActionMethod() -``` + + **MaxRequestBodySize** -Here's an example that shows how to configure the constraint for the entire application, every request: + The maximum allowed size of any request body in bytes. When set to `null`, the maximum request body size is unlimited. This limit has no effect on upgraded connections, which are always unlimited. -[!code-csharp[](httpsys/sample/Program.cs?name=snippet_Options&highlight=6)] + The recommended method to override the limit in an ASP.NET Core MVC app for a single `IActionResult` is to use the [RequestSizeLimitAttribute](/dotnet/api/microsoft.aspnetcore.mvc.requestsizelimitattribute) attribute on an action method: + + ```csharp + [RequestSizeLimit(100000000)] + public IActionResult MyActionMethod() + ``` -You can override the setting on a specific request in *Startup.cs*: + An exception is thrown if the app attempts to configure the limit on a request after the app has started reading the request. An `IsReadOnly` property can be used to indicate if the `MaxRequestBodySize` property is in a read-only state, meaning it's too late to configure the limit. -[!code-csharp[](httpsys/sample/Startup.cs?name=snippet_Configure&highlight=9-10)] - -An exception is thrown if you try to configure the limit on a request after the application has started reading the request. There's an `IsReadOnly` property that tells you if the `MaxRequestBodySize` property is in read-only state, meaning it's too late to configure the limit. + If the app should override [MaxRequestBodySize](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.maxrequestbodysize) per-request, use the [IHttpMaxRequestBodySizeFeature](/dotnet/api/microsoft.aspnetcore.http.features.ihttpmaxrequestbodysizefeature): -For information about other HTTP.sys options, see [HttpSysOptions](https://github.com/aspnet/HttpSysServer/blob/rel/2.0.0/src/Microsoft.AspNetCore.Server.HttpSys/HttpSysOptions.cs). + [!code-csharp[](httpsys/sample/Startup.cs?name=snippet1&highlight=6-7)] -### Configure URLs and ports to listen on +1. If using Visual Studio, make sure the app isn't configured to run IIS or IIS Express. -By default ASP.NET Core binds to `http://localhost:5000`. To configure URL prefixes and ports, you can use the `UseUrls` extension method, the `urls` command-line argument, the ASPNETCORE_URLS environment variable, or the `UrlPrefixes` property on [HttpSysOptions](https://github.com/aspnet/HttpSysServer/blob/rel/2.0.0/src/Microsoft.AspNetCore.Server.HttpSys/HttpSysOptions.cs). The following code example uses `UrlPrefixes`. + In Visual Studio, the default launch profile is for IIS Express. To run the project as a console app, manually change the selected profile, as shown in the following screen shot: -[!code-csharp[](httpsys/sample/Program.cs?name=snippet_Main&highlight=17)] + ![Select console app profile](httpsys/_static/vs-choose-profile.png) -An advantage of `UrlPrefixes` is that you get an error message immediately if you try to add a prefix that's formatted wrong. An advantage of `UseUrls` (shared with `urls` and ASPNETCORE_URLS) is that you can more easily switch between Kestrel and HTTP.sys. +### Configure Windows Server -If you use both `UseUrls` (or `urls` or ASPNETCORE_URLS) and `UrlPrefixes`, the settings in `UrlPrefixes` override the ones in `UseUrls`. For more information, see [Hosting](xref:fundamentals/hosting). +1. If the app is a [framework-dependent deployment](/dotnet/core/deploying/#framework-dependent-deployments-fdd), install .NET Core, .NET Framework, or both (if the app is a .NET Core app targeting the .NET Framework). -HTTP.sys uses the [HTTP Server API UrlPrefix string formats](https://msdn.microsoft.com/library/windows/desktop/aa364698.aspx). + * **.NET Core** – If the app requires .NET Core, obtain and run the .NET Core installer from [.NET Downloads](https://www.microsoft.com/net/download/windows). + * **.NET Framework** – If the app requires .NET Framework, see [.NET Framework: Installation guide](/dotnet/framework/install/) to find installation instructions. Install the required .NET Framework. The installer for the latest .NET Framework can be found at [.NET Downloads](https://www.microsoft.com/net/download/windows). -> [!NOTE] -> Make sure that you specify the same prefix strings in `UseUrls` or `UrlPrefixes` that you preregister on the server. +1. Configure URLs and ports for the app. -### Don't use IIS + By default, ASP.NET Core binds to `http://localhost:5000`. To configure URL prefixes and ports, options include using: -Make sure your application isn't configured to run IIS or IIS Express. + * [UseUrls](/dotnet/api/microsoft.aspnetcore.hosting.hostingabstractionswebhostbuilderextensions.useurls) + * `urls` command-line argument + * `ASPNETCORE_URLS` environment variable + * [UrlPrefixes](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.urlprefixes) -In Visual Studio, the default launch profile is for IIS Express. To run the project as a console application, manually change the selected profile, as shown in the following screen shot. + The following code example shows how to use [UrlPrefixes](/dotnet/api/microsoft.aspnetcore.server.httpsys.httpsysoptions.urlprefixes): -![Select console app profile](httpsys/_static/vs-choose-profile.png) + [!code-csharp[](httpsys/sample/Program.cs?name=snippet1&highlight=11)] -## Preregister URL prefixes and configure SSL + An advantage of `UrlPrefixes` is that an error message is generated immediately for improperly formatted prefixes. -Both IIS and HTTP.sys rely on the underlying Http.Sys kernel mode driver to listen for requests and do initial processing. In IIS, the management UI gives you a relatively easy way to configure everything. However, you need to configure Http.Sys yourself. The built-in tool for doing that's *netsh.exe*. + The settings in `UrlPrefixes` override `UseUrls`/`urls`/`ASPNETCORE_URLS` settings. Therefore, an advantage of `UseUrls`, `urls`, and the `ASPNETCORE_URLS` environment variable is that it's easier to switch between Kestrel and HTTP.sys. For more information on `UseUrls`, `urls`, and `ASPNETCORE_URLS`, see [Hosting](xref:fundamentals/hosting). -With *netsh.exe* you can reserve URL prefixes and assign SSL certificates. The tool requires administrative privileges. + HTTP.sys uses the [HTTP Server API UrlPrefix string formats](https://msdn.microsoft.com/library/windows/desktop/aa364698.aspx). -The following example shows the minimum needed to reserve URL prefixes for ports 80 and 443: +1. Preregister URL prefixes to bind to HTTP.sys and set up x.509 certificates. -```console -netsh http add urlacl url=http://+:80/ user=Users -netsh http add urlacl url=https://+:443/ user=Users -``` + If URL prefixes aren't preregistered in Windows, run the app with administrator privileges. The only exception is when binding to localhost using HTTP (not HTTPS) with a port number greater than 1024. In that case, administrator privileges aren't required. -The following example shows how to assign an SSL certificate: + 1. The built-in tool for configuring HTTP.sys is *netsh.exe*. *netsh.exe* is used to reserve URL prefixes and assign X.509 certificates. The tool requires administrator privileges. -```console -netsh http add sslcert ipport=0.0.0.0:443 certhash=MyCertHash_Here appid={00000000-0000-0000-0000-000000000000}" -``` + The following example shows the commands to reserve URL prefixes for ports 80 and 443: -Here is the reference documentation for *netsh.exe*: + ```console + netsh http add urlacl url=http://+:80/ user=Users + netsh http add urlacl url=https://+:443/ user=Users + ``` -* [Netsh Commands for Hypertext Transfer Protocol (HTTP)](https://technet.microsoft.com/library/cc725882.aspx) -* [UrlPrefix Strings](https://msdn.microsoft.com/library/windows/desktop/aa364698.aspx) + The following example shows how to assign an X.509 certificate: -The following resources provide detailed instructions for several scenarios. Articles that refer to HttpListener apply equally to HTTP.sys, as both are based on Http.Sys. + ```console + netsh http add sslcert ipport=0.0.0.0:443 certhash=MyCertHash_Here appid={00000000-0000-0000-0000-000000000000}" + ``` -* [How to: Configure a Port with an SSL Certificate](https://docs.microsoft.com/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate) -* [HTTPS Communication - HttpListener based Hosting and Client Certification](http://sunshaking.blogspot.com/2012/11/https-communication-httplistener-based.html) This is a third-party blog and is fairly old but still has useful information. -* [How To: Walkthrough Using HttpListener or Http Server unmanaged code (C++) as an SSL Simple Server](https://blogs.msdn.microsoft.com/jpsanders/2009/09/29/how-to-walkthrough-using-httplistener-or-http-server-unmanaged-code-c-as-an-ssl-simple-server/) This too is an older blog with useful information. + Reference documentation for *netsh.exe*: -Here are some third-party tools that can be easier to use than the *netsh.exe* command line. These are not provided by or endorsed by Microsoft. The tools run as administrator by default, since *netsh.exe* itself requires administrator privileges. + * [Netsh Commands for Hypertext Transfer Protocol (HTTP)](https://technet.microsoft.com/library/cc725882.aspx) + * [UrlPrefix Strings](https://msdn.microsoft.com/library/windows/desktop/aa364698.aspx) -* [http.sys Manager](http://httpsysmanager.codeplex.com/) provides UI for listing and configuring SSL certificates and options, prefix reservations, and certificate trust lists. -* [HttpConfig](http://www.stevestechspot.com/ABetterHttpcfg.aspx) lets you list or configure SSL certificates and URL prefixes. The UI is more refined than http.sys Manager and exposes a few more configuration options, but otherwise it provides similar functionality. It cannot create a new certificate trust list (CTL), but can assign existing ones. + 1. Create self-signed X.509 certificates, if required. -[!INCLUDE[How to make an SSL cert](../../includes/make-ssl-cert.md)] + [!INCLUDE[How to make an X.509 cert](../../includes/make-x509-cert.md)] -## Next steps +1. Open firewall ports to allow traffic to reach HTTP.sys. Use *netsh.exe* or [PowerShell cmdlets](https://technet.microsoft.com/library/jj554906). -For more information, see the following resources: +## Additional resources -* [Sample app for this article](https://github.com/aspnet/Docs/tree/master/aspnetcore/fundamentals/servers/httpsys/sample) -* [HTTP.sys source code](https://github.com/aspnet/HttpSysServer/) +* [HTTP Server API](https://msdn.microsoft.com/library/windows/desktop/aa364510.aspx) +* [aspnet/HttpSysServer GitHub repository (source code)](https://github.com/aspnet/HttpSysServer/) * [Hosting](xref:fundamentals/hosting) diff --git a/aspnetcore/fundamentals/servers/httpsys/_static/vs-choose-profile.png b/aspnetcore/fundamentals/servers/httpsys/_static/vs-choose-profile.png index 4fcd45e7fe8c..1dde2fd08193 100644 Binary files a/aspnetcore/fundamentals/servers/httpsys/_static/vs-choose-profile.png and b/aspnetcore/fundamentals/servers/httpsys/_static/vs-choose-profile.png differ diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/.bowerrc b/aspnetcore/fundamentals/servers/httpsys/sample/.bowerrc new file mode 100644 index 000000000000..6406626abfef --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "wwwroot/lib" +} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/HttpSysDemo.csproj b/aspnetcore/fundamentals/servers/httpsys/sample/HttpSysSample.csproj similarity index 87% rename from aspnetcore/fundamentals/servers/httpsys/sample/HttpSysDemo.csproj rename to aspnetcore/fundamentals/servers/httpsys/sample/HttpSysSample.csproj index c0316bc269af..ebf007d1f60e 100644 --- a/aspnetcore/fundamentals/servers/httpsys/sample/HttpSysDemo.csproj +++ b/aspnetcore/fundamentals/servers/httpsys/sample/HttpSysSample.csproj @@ -2,11 +2,10 @@ netcoreapp2.0 - Exe - + diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Error.cshtml b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Error.cshtml new file mode 100644 index 000000000000..0341fe884a5f --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Error.cshtml @@ -0,0 +1,23 @@ +@page +@model ErrorModel +@{ + ViewData["Title"] = "Error"; +} + +

Error.

+

An error occurred while processing your request.

+ +@if (Model.ShowRequestId) +{ +

+ Request ID: @Model.RequestId +

+} + +

Development Mode

+

+ Swapping to the Development environment displays detailed information about the error that occurred. +

+

+ The Development environment shouldn't be enabled for deployed applications. It can result in displaying sensitive information from exceptions to end users. For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development and restarting the app or adding .UseEnvironment("Development") to WebHost in Program.cs and restarting the app. +

diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Error.cshtml.cs b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Error.cshtml.cs new file mode 100644 index 000000000000..6e5ae9327c1e --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Error.cshtml.cs @@ -0,0 +1,17 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace HttpSysSample.Pages +{ + public class ErrorModel : PageModel + { + public string RequestId { get; private set; } + + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + + public void OnGet() + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; + } + } +} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Index.cshtml b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Index.cshtml new file mode 100644 index 000000000000..3e34bda5655b --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Index.cshtml @@ -0,0 +1,28 @@ +@page +@model IndexModel +@{ + ViewData["Title"] = "HTTP.sys Demo"; +} + +

@ViewData["Title"]

+ +
+
+
+
+

Instructions

+
+
+

Run the app from a command prompt by executing the following command from the project's folder:

+

dotnet run

+

Logging indicates that the HttpSysListener is ready to receive requests:

+

+

info: Microsoft.AspNetCore.Server.HttpSys.HttpSysListener[0]
+    Start
+info: Microsoft.AspNetCore.Server.HttpSys.HttpSysListener[0]
+    Listening on prefix: http://localhost:5000/
+

+
+
+
+
diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Index.cshtml.cs b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Index.cshtml.cs new file mode 100644 index 000000000000..9b0aa8048871 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/Index.cshtml.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace HttpSysSample.Pages +{ + public class IndexModel : PageModel + { + public void OnGet() + { + } + } +} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/Pages/_Layout.cshtml b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/_Layout.cshtml new file mode 100644 index 000000000000..4415f623a350 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/_Layout.cshtml @@ -0,0 +1,70 @@ + + + + + + @ViewData["Title"] + + + + + + + + + + + +
+ @RenderBody() +
+ +
+ + + + + + + + + + + + + @RenderSection("Scripts", required: false) + + diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/Pages/_ViewImports.cshtml b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/_ViewImports.cshtml new file mode 100644 index 000000000000..31bcc8509675 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using HttpSysSample +@namespace HttpSysSample.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/Pages/_ViewStart.cshtml b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/_ViewStart.cshtml new file mode 100644 index 000000000000..a5f10045db97 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/Pages/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout"; +} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/Program.cs b/aspnetcore/fundamentals/servers/httpsys/sample/Program.cs index dc8ed4850e63..0604d6824fe8 100644 --- a/aspnetcore/fundamentals/servers/httpsys/sample/Program.cs +++ b/aspnetcore/fundamentals/servers/httpsys/sample/Program.cs @@ -1,38 +1,29 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Server.HttpSys; -using System; -// The default listening address is http://localhost:5000 if none is specified. - -namespace HttpSysDemo +namespace HttpSysSample { - /// - /// Executing the "dotnet run" command in the application folder will run this app. - /// public class Program { - #region snippet_Main public static void Main(string[] args) { - Console.WriteLine("Running demo with HTTP.sys."); - BuildWebHost(args).Run(); } + #region snippet1 public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() - #region snippet_Options .UseHttpSys(options => { + // The following options are set to default values. options.Authentication.Schemes = AuthenticationSchemes.None; options.Authentication.AllowAnonymous = true; - options.MaxConnections = 100; + options.MaxConnections = null; options.MaxRequestBodySize = 30000000; options.UrlPrefixes.Add("http://localhost:5000"); }) - #endregion .Build(); #endregion } diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/README.md b/aspnetcore/fundamentals/servers/httpsys/sample/README.md new file mode 100644 index 000000000000..cc8aba58b3f5 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/README.md @@ -0,0 +1,3 @@ +# ASP.NET Core HTTP.sys Sample + +This sample illustrates the use of HTTP.sys. This sample demonstrates the features described in the [HTTP.sys web server implementation](https://docs.microsoft.com/aspnet/core/fundamentals/servers/httpsys) topic. diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/Startup.cs b/aspnetcore/fundamentals/servers/httpsys/sample/Startup.cs index a41518f2bdaa..b8a0b23c712d 100644 --- a/aspnetcore/fundamentals/servers/httpsys/sample/Startup.cs +++ b/aspnetcore/fundamentals/servers/httpsys/sample/Startup.cs @@ -1,38 +1,49 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Server.Features; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Http.Features; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace HttpSysDemo +namespace HttpSysSample { public class Startup { - #region snippet_Configure - public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) + public void ConfigureServices(IServiceCollection services) { - var serverAddressesFeature = app.ServerFeatures.Get(); - - app.UseStaticFiles(); + services.AddMvc(); + } - app.Run(async (context) => + #region snippet1 + public void Configure(IApplicationBuilder app, IHostingEnvironment env, + ILogger logger) + { + app.Use(async (context, next) => { context.Features.Get() .MaxRequestBodySize = 10 * 1024; - context.Response.ContentType = "text/html"; - await context.Response.WriteAsync("

Hosted by HTTP.sys

"); + var serverAddressesFeature = app.ServerFeatures.Get(); + var addresses = string.Join(", ", serverAddressesFeature?.Addresses); - if (serverAddressesFeature != null) - { - await context.Response.WriteAsync($"

Listening on the following addresses: {string.Join(", ", serverAddressesFeature.Addresses)}

"); - } + logger.LogInformation($"Addresses: {addresses}"); - await context.Response.WriteAsync($"

Request URL: {context.Request.GetDisplayUrl()}

"); + await next.Invoke(); }); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseDatabaseErrorPage(); + } + else + { + app.UseExceptionHandler("/Error"); + } + + app.UseStaticFiles(); + app.UseMvc(); } -#endregion + #endregion } } diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/appsettings.Development.json b/aspnetcore/fundamentals/servers/httpsys/sample/appsettings.Development.json new file mode 100644 index 000000000000..fa8ce71a97a3 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/appsettings.Production.json b/aspnetcore/fundamentals/servers/httpsys/sample/appsettings.Production.json new file mode 100644 index 000000000000..05d41950658c --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/appsettings.Production.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Error", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/appsettings.json b/aspnetcore/fundamentals/servers/httpsys/sample/appsettings.json new file mode 100644 index 000000000000..20aa907654ab --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug" + } + } +} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/bower.json b/aspnetcore/fundamentals/servers/httpsys/sample/bower.json new file mode 100644 index 000000000000..b07e3cc5ae5d --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/bower.json @@ -0,0 +1,10 @@ +{ + "name": "asp.net", + "private": true, + "dependencies": { + "bootstrap": "3.3.7", + "jquery": "2.2.0", + "jquery-validation": "1.14.0", + "jquery-validation-unobtrusive": "3.2.6" + } +} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/bundleconfig.json b/aspnetcore/fundamentals/servers/httpsys/sample/bundleconfig.json new file mode 100644 index 000000000000..6d3f9a57aea2 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/bundleconfig.json @@ -0,0 +1,24 @@ +// Configure bundling and minification for the project. +// More info at https://go.microsoft.com/fwlink/?LinkId=808241 +[ + { + "outputFileName": "wwwroot/css/site.min.css", + // An array of relative input file paths. Globbing patterns supported + "inputFiles": [ + "wwwroot/css/site.css" + ] + }, + { + "outputFileName": "wwwroot/js/site.min.js", + "inputFiles": [ + "wwwroot/js/site.js" + ], + // Optionally specify minification options + "minify": { + "enabled": true, + "renameLocals": true + }, + // Optionally generate .map file + "sourceMap": false + } +] diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/css/site.css b/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/css/site.css new file mode 100644 index 000000000000..64634c996c41 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/css/site.css @@ -0,0 +1,25 @@ +body { + padding-top: 50px; + padding-bottom: 20px; +} + +h1 { + font-size: 24px; +} + +h2 { + font-size: 20px; +} + +h3 { + font-size:16px +} + +.body-content { + padding-left: 15px; + padding-right: 15px; +} + +.panel-body { + font-size: 16px; +} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/css/site.min.css b/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/css/site.min.css new file mode 100644 index 000000000000..099af93ef1d3 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/css/site.min.css @@ -0,0 +1 @@ +body{padding-top:50px;padding-bottom:20px}h1{font-size:24px}h2{font-size:20px}h3{font-size:16px}.body-content{padding-left:15px;padding-right:15px}.panel-body{font-size:16px} diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/favicon.ico b/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/favicon.ico new file mode 100644 index 000000000000..a3a799985c43 Binary files /dev/null and b/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/favicon.ico differ diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/js/site.js b/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/js/site.js new file mode 100644 index 000000000000..82ecce7b4a78 --- /dev/null +++ b/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/js/site.js @@ -0,0 +1 @@ +// Write your Javascript code. diff --git a/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/js/site.min.js b/aspnetcore/fundamentals/servers/httpsys/sample/wwwroot/js/site.min.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/aspnetcore/fundamentals/servers/kestrel.md b/aspnetcore/fundamentals/servers/kestrel.md index 5168465a14f6..3f19cbd563c7 100644 --- a/aspnetcore/fundamentals/servers/kestrel.md +++ b/aspnetcore/fundamentals/servers/kestrel.md @@ -179,7 +179,7 @@ The `Listen` method binds to a TCP socket, and an options lambda lets you config Notice how this example configures SSL for a particular endpoint by using [ListenOptions](https://github.com/aspnet/KestrelHttpServer/blob/rel/2.0.0/src/Microsoft.AspNetCore.Server.Kestrel.Core/ListenOptions.cs). You can use the same API to configure other Kestrel settings for particular endpoints. -[!INCLUDE[How to make an SSL cert](../../includes/make-ssl-cert.md)] +[!INCLUDE[How to make an X.509 cert](../../includes/make-x509-cert.md)] **Bind to a Unix socket** @@ -333,7 +333,7 @@ var host = new WebHostBuilder() > [!NOTE] > HTTPS and HTTP cannot be hosted on the same port. -[!INCLUDE[How to make an SSL cert](../../includes/make-ssl-cert.md)] +[!INCLUDE[How to make an X.509 cert](../../includes/make-x509-cert.md)] --- ## Next steps diff --git a/aspnetcore/includes/make-ssl-cert.md b/aspnetcore/includes/make-ssl-cert.md deleted file mode 100644 index 8f0d7b1b4dc3..000000000000 --- a/aspnetcore/includes/make-ssl-cert.md +++ /dev/null @@ -1,3 +0,0 @@ -For generating self-signed SSL certificates on Windows, you can use the PowerShell cmdlet [New-SelfSignedCertificate](/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps). For a third-party tool that makes it easier for you to generate self-signed certificates, see [SelfCert](https://www.pluralsight.com/blog/software-development/selfcert-create-a-self-signed-certificate-interactively-gui-or-programmatically-in-net). - -On macOS and Linux you can create a self-signed certificate using [OpenSSL](https://www.openssl.org/). diff --git a/aspnetcore/includes/make-x509-cert.md b/aspnetcore/includes/make-x509-cert.md new file mode 100644 index 000000000000..f2e168a2caa9 --- /dev/null +++ b/aspnetcore/includes/make-x509-cert.md @@ -0,0 +1,3 @@ +On Windows, self-signed certificates can be created using the [New-SelfSignedCertificate PowerShell cmdlet](/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps). For an unsupported example, see [UpdateIISExpressSSLForChrome.ps1](https://github.com/aspnet/Docs/tree/master/aspnetcore/includes/make-x509-cert/UpdateIISExpressSSLForChrome.ps1). + +On macOS, Linux, and Windows, certificates can be created using [OpenSSL](https://www.openssl.org/). diff --git a/aspnetcore/includes/make-x509-cert/UpdateIISExpressSSLForChrome.ps1 b/aspnetcore/includes/make-x509-cert/UpdateIISExpressSSLForChrome.ps1 new file mode 100644 index 000000000000..756f4553bed3 --- /dev/null +++ b/aspnetcore/includes/make-x509-cert/UpdateIISExpressSSLForChrome.ps1 @@ -0,0 +1,63 @@ +# Create a new self-signed certificate for IIS Express. +# +# Provides a subjectAltName (SAN) to satisfy Chrome 58 or later. +# See https://bugs.chromium.org/p/chromium/issues/detail?id=308330 +# +# Run the script at an administrative PowerShell prompt. +# +# When prompted to trust a new certificate via a Windows dialog, +# select Yes. Otherwise, Visual Studio won't be able to determine +# the process ID when the web app is launched. +# +# THIS SCRIPT IS UNSUPPORTED BY MICROSOFT AND PROVIDED "AS IS" +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. + +$certificate = New-SelfSignedCertificate ` + -Subject localhost ` + -DnsName localhost ` + -KeyAlgorithm RSA ` + -KeyLength 2048 ` + -NotBefore (Get-Date) ` + -NotAfter (Get-Date).AddYears(5) ` + -CertStoreLocation "cert:CurrentUser\My" ` + -FriendlyName "IIS Express Development Certificate" ` + -HashAlgorithm SHA256 ` + -KeyUsage DigitalSignature, KeyEncipherment, DataEncipherment ` + -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1") +$certificatePath = 'Cert:\CurrentUser\My\' + ($certificate.ThumbPrint) + +# Export the certificate to a PFX (PKCS #12). +$pfxPassword = ConvertTo-SecureString ([Guid]::NewGuid().ToString()) -Force -AsPlainText +$pfxFilePath = [system.io.path]::GetTempFileName() +$cerFilePath = [system.io.path]::GetTempFileName() + +Export-PfxCertificate -Cert $certificatePath -FilePath $pfxFilePath -Password $pfxPassword +Export-Certificate -Cert $certificatePath -FilePath $cerFilePath + +# Now that the certificate has been exported, delete the cert. +Remove-Item $certificatePath + +# Add the certificate to the machine personal store, so netsh can bind. +Import-PfxCertificate -FilePath $pfxFilePath Cert:\LocalMachine\My -Password $pfxPassword -Exportable + +# Add the certificate to the user root store, so trust is enabled. +# When the prompt appears to trust a new certificate via a Windows dialog, +# select Yes. Otherwise, Visual Studio won't be able to determine the +# process ID when the web app is launched. +Import-Certificate -FilePath $cerFilePath -CertStoreLocation Cert:\CurrentUser\Root + +# Bind using netsh. The app ID is the IIS Express app ID. +for ($port = 44300; $port -lt 44400; $port++) +{ + $command = "http delete sslcert ipport=0.0.0.0:$port" + Write-Output $command + $command | netsh + + $command = "http add sslcert ipport=0.0.0.0:$port certhash="+$($certificate.Thumbprint)+" appid={214124cd-d05b-4309-9af9-9caa44b2b74a}" + Write-Output $command + $command | netsh +} + +# Clean up the temporary PFX. +Remove-Item $pfxFilePath +Remove-Item $cerFilePath