Skip to content

New kestrel configuration & related APIs #6102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 1, 2018

Conversation

guardrex
Copy link
Collaborator

@guardrex guardrex commented Apr 27, 2018

Fixes #5056
Fixes #6129

Internal Review Topic

Much of this was derived from aspnet/KestrelHttpServer#2186. However, I made a big pass on the whole topic, too, in an attempt to polish it up (e.g., API topic links, xref links, code fencing, lists, grammar+style, and sample touch-ups).

@guardrex guardrex requested a review from Tratcher April 27, 2018 18:52
Copy link
Member

@Tratcher Tratcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some initial notes, more to follow.

The [Microsoft.AspNetCore.Server.Kestrel](https://www.nuget.org/packages/Microsoft.AspNetCore.Server.Kestrel/) package is included in the [Microsoft.AspNetCore.All metapackage](xref:fundamentals/metapackage).

ASP.NET Core project templates use Kestrel by default. In *Program.cs*, the template code calls `CreateDefaultBuilder`, which calls [UseKestrel](https://docs.microsoft.com/aspnet/core/api/microsoft.aspnetcore.hosting.webhostbuilderkestrelextensions#Microsoft_AspNetCore_Hosting_WebHostBuilderKestrelExtensions_UseKestrel_Microsoft_AspNetCore_Hosting_IWebHostBuilder_) behind the scenes.
ASP.NET Core project templates use Kestrel by default. In *Program.cs*, the template code calls [CreateDefaultBuilder](/dotnet/api/microsoft.aspnetcore.webhost.createdefaultbuilder), which calls [UseKestrel](/dotnet/api/microsoft.aspnetcore.hosting.webhostbuilderkestrelextensions.usekestrel) behind the scenes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why even show an example that calls UseKestrel in this scenario?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, it doesn't look like (Tom?) was trying to show that ... I think he's going for an example of the ...

ASP.NET Core project templates use Kestrel by default ... CreateDefaultBuilder ... calls UseKestrel

... bit. It looks like he's just making reference to the CreateDefaultBuilder line at this point.

Then, it looks like he wanted to show the options config, either to show the ListenOptions and/or a cert being used ... or perhaps just for some context early in the topic.

I'm just guessing, of course.

Would you like me to strike the UseKestrel?

I should mention that when 2.1 ships that this topic is going to get a green dino samples treatment: #5495. For now, I'm just trying to work with what we have as best I can. We aren't going to have 2.0 and 2.1 samples ... only 2.x ... and 2.x = 2.0 now and 2.x = 2.1 at 2.1 RTM.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing UseKestrel would be more clear here, showing that the app can run without it.


* You can't use SSL with these methods.
* If you use both the `Listen` method and `UseUrls`, the `Listen` endpoints override the `UseUrls` endpoints.
* SSL can't be used with these approaches.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except... SSL/HTTPS now works with these scenarios if you provide a default certificate through one of the new configuration mechanisms (e.g. config file, ConfgiureHttpsDefaults, etc).

@@ -197,7 +197,7 @@ ASP.NET Core 2.1 and later project templates configure apps to run on HTTPS by d

Call [Listen](/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserveroptions.listen) or [ListenUnixSocket](/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserveroptions.listenunixsocket) methods on [KestrelServerOptions](/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserveroptions) to configure URL prefixes and ports for Kestrel.

`UseUrls`, the `--urls` command-line argument, `urls` host configuration key, and the `ASPNETCORE_URLS` environment variable also work but have the limitations noted later in this section (a default certificate must be available for HTTPS endpoint configuration).
`UseUrls`, the `--urls` command-line argument, `urls` host configuration key, and the `ASPNETCORE_URLS` environment variable also work but have a limitations noted later in this section (a default certificate must be available for HTTPS endpoint configuration).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: limitation instead of limitations

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will work out to "the limitations" (plural), so I'm reverting. There will be two (unless we change that). I reacted to Chris's remark on the last commit. It's down at lines 407-408.

Copy link
Member

@Tratcher Tratcher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something seems wrong with your review link, it's not showing most of the new content like the json config files.

If you specify port number 0, Kestrel dynamically binds to an available port. The following example shows how to determine which port Kestrel actually bound to at runtime:
When the port number is `0` is specified, Kestrel dynamically binds to an available port. The following example shows how to determine which port Kestrel actually bound at runtime:

[!code-csharp[](kestrel/samples/2.x/Startup.cs?name=snippet_Configure&highlight=3-4,17-20)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sample is pretty ironic because you wouldn't be able to connect to the site without knowing the port. The real port will be reported in the console output "Now listening on:". That might be better to show here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The port is never set to 0 anyway in the sample. I'll add a demo of it and the console window output.

@guardrex
Copy link
Collaborator Author

guardrex commented Apr 27, 2018

Something seems wrong with your review link, it's not showing most of the new content like the json config files.

I think it's the conceptual versioning. I don't have access to the internal review topics, and they don't build locally correctly. @Rick-Anderson and/or @scottaddie will need to help with layout if versioning isn't working well. I'm only aware of bad lists and bad code blocks (e.g., #6052) ... not sure about content not showing at all.

[EDIT] In case ur wondering why that endpoints section is so FLAT, I was avoiding two-level lists because of the rendering problems. I'm making greater use of headings on purpose. Not really my first choice in all cases, but I think it works ok under the circumstances.

@Tratcher
Copy link
Member

Yea, it's not showing any of your new content under Endpoint configuration, I only see the 2.0 content. In the raw HTML I see a separate div for 2.1 that's hidden for some reason.


* `ASPNETCORE_URLS` environment variable.
* `--urls` command-line argument.
* `urls` host configuration key.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's important to distinguish that this must come from the host configuration, not the app configuration. There's an FAQ where people try to set Urls in appsettings.json and it doesn't work because appsettings.json isn't read until after the host is initialized. aspnet/MetaPackages#247. Kestrel's new config schema doesn't have this limitation, it reads directly from the config much later in the startup process.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to address this under line 175 because that's where the 2.0 mention of the urls config key is covered.


*Replace the default certificate from configuration*

Call `serverOptions.Configure(context.Configuration.GetSection("Kestrel"))` to specify the configuration section. A default HTTPS app settings configuration schema is available for Kestrel. Configure multiple endpoints, including the URLs and the certificates to use, either from a file on disk or from a certificate store.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Configure call is included by default in WebHost.CreateDefaultBuilder.

In the following *appSettings.json* example:

* Set **AllowInvalid** to `true` to permit the use of invalid certificates (for example, self-signed certificates).
* **HttpsDefaultCert** indicates use of the cert defined under **Certificates** > **Default** or the development certificate.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like the name HttpsDefaultCert is special. Any https endpoint that does not specify a certificate will fall back to the the default specified the the Certificates section or elsewhere in code.

}
```

An alternative to using **Path** and **Password** for the **Certificates** > **Default** certificate specification is to specify the certificate using the certificate store fields:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or for any certificate node.

serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
.Endpoint("HTTPS", opt =>
{
opt.ListenOptions.Protocols = HttpProtocols.Http1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We removed the Protocols property for 2.1.


*Change the defaults in code*

`ConfigureEndpointDefaults` and `ConfigureHttpsDefaults` can be used to change default settings for `ListenOptions` and `HttpsConnectionAdapterOptions`, including overriding the default certificate specified in the prior scenario.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They should be called before any endpoints are configured.

```csharp
options.ConfigureEndpointDefaults(opt =>
{
opt.Protocols = HttpProtocols.Http1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove Protocols, you can set nagle instead.

@Rick-Anderson
Copy link
Contributor

@Tratcher Do you have version 2.1 selected?
image

@Tratcher
Copy link
Member

Ah, I'd missed that. It defaulted to 1.0. Thanks Rick.

* `UseHttps(X509Certificate2 serverCertificate)`
* `UseHttps(X509Certificate2 serverCertificate, Action<HttpsConnectionAdapterOptions> configureOptions)`
* `UseHttps(Action<HttpsConnectionAdapterOptions> configureOptions)`
* `UseHttps(HttpsConnectionAdapterOptions httpsOptions)`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caveat: Don't use this overload, it bypasses all of the defaults logic and is only here for back compat and advanced scenarios.


```json
{
"Kestrel": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason the rendered version flattens this JSON.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason the rendered version flattens this JSON.

See: #6052

* `serverOptions.Configure(context.Configuration.GetSection("Kestrel"))` returns a `KestrelConfigurationLoader` with an `.Endpoint(string name, options => { })` method that can be used to supplement a configured endpoint's settings:

```csharp
serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also directly access KestrelServerOptions.ConfigurationLoader to keep iterating on the existing loader, such as the one provided by WebHost.CreatedDeafaultBuilder.

@guardrex
Copy link
Collaborator Author

@Tratcher We don't have Kestrel support for SNI in here, and I think we should add it ... sound good?

@Tratcher
Copy link
Member

By all means.

@guardrex
Copy link
Collaborator Author

guardrex commented Apr 29, 2018

@blowdart We're adding a bit for Kestrel SNI support. The passage goes like this ...

Kestrel support for SNI

[Server Name Indication (SNI)](https://docs.microsoft.com/windows-server/security/tls/transport-layer-security-protocol#BKMK_SNI) can be used to host multiple domains on the same IP address and port. For SNI to function, the client sends the host name for the secure session to the server during the TLS handshake so that the server can provide the correct certificate. The client uses the furnished certificate for encrypted communication with the server during the secure session that follows the TLS handshake.

Kestrel supports SNI via the ServerCertificateSelector callback. The callback is invoked once per connection to allow the app to inspect the host name and select the appropriate certificate.

SNI support requires running on target framework netcoreapp2.1. On netcoreapp2.0 and net461, the callback is invoked but the name is always null. The name is also null if the client doesn't provide the host name parameter in the TLS handshake.

... with the code sample from the blog post ( https://blogs.msdn.microsoft.com/webdev/2018/04/12/asp-net-core-2-1-0-preview2-now-available/ ). Corrections/suggestions? ... and is that a decent link for "Server Name Indication (SNI)"?

@blowdart
Copy link
Contributor

SNI link - https://tools.ietf.org/html/rfc6066#section-3

And that sample seems fine.

certs["example.com"] = exampleCert;
certs["sub.example.com"] = subExampleCert;

httpsOptions.ServerCertificateSelector = (features, name) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guardrex guardrex requested a review from scottaddie April 30, 2018 17:01
* Maximum request body size
* Minimum request body data rate

Set these and other constraints on the `Limits` property of the [KestrelServerOptions](/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserveroptions) class. The `Limits` property holds an instance of the [KestrelServerLimits](/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserverlimits) class.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the first sentence, remove the code-fencing on Limits and link to its API ref:
/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserveroptions.limits


```csharp
[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()
```

Here's an example that shows how to configure the constraint for the entire application, every request:
Here's an example that shows how to configure the constraint for the entire app, every request:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the ", every request" portion of this sentence be removed? Or maybe that should say ", on every request"?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's drop "entire," too.

Here's an example that shows how to configure the constraint for the app on every request:


[WebHost.CreateDefaultBuilder](/dotnet/api/microsoft.aspnetcore.webhost.createdefaultbuilder) calls `serverOptions.Configure(context.Configuration.GetSection("Kestrel"))` by default to load Kestrel configuration. A default HTTPS app settings configuration schema is available for Kestrel. Configure multiple endpoints, including the URLs and the certificates to use, either from a file on disk or from a certificate store.

In the following *appSettings.json* example:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

appSettings.json --> appsettings.json


**Port 0**

If you specify port number 0, Kestrel dynamically binds to an available port. The following example shows how to determine which port Kestrel actually bound to at runtime:
When the port number is `0` is specified, Kestrel dynamically binds to an available port. The following example shows how to determine which port Kestrel actually bound at runtime:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the port number is 0 is specified


If you use IIS, the URL bindings for IIS override any bindings that you set by calling either `Listen` or `UseUrls`. For more information, see [Introduction to ASP.NET Core Module](aspnet-core-module.md).
When using IIS, the URL bindings for IIS override bindings set by either `Listen` or `UseUrls`. For more information, see the [ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module) topic.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the word "are" appear before "set by either"?

You can also directly access `KestrelServerOptions.ConfigurationLoader` to keep iterating on the existing loader, such as the one provided by `WebHost.CreatedDeafaultBuilder`.

* The configuration section for each endpoint is a available on the options in the `Endpoint` method so that custom settings may be read.
* Multiple configurations may be loaded by calling `serverOptions.Configure(context.Configuration.GetSection("Kestrel"))` again with another section. Only the last configuration is used unless `Load` is explicitly called on prior instances. The metapackage doesn't call `Load` so that its default configuration section may be replaced.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comma after "Only the last configuration is used".

@guardrex
Copy link
Collaborator Author

ty @Tratcher and @scottaddie

@halter73 About to merge this one ... do you have any additional corrections/suggestions?

@guardrex guardrex merged commit 7c57723 into master May 1, 2018
@guardrex guardrex deleted the guardrex/kestrel-endpoint-config branch May 1, 2018 23:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants