Skip to content
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

Read additional KestrelServerOptions from config #4765

Open
Tratcher opened this issue Dec 12, 2017 · 34 comments
Open

Read additional KestrelServerOptions from config #4765

Tratcher opened this issue Dec 12, 2017 · 34 comments
Labels
affected-few This issue impacts only small number of customers area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-kestrel help candidate Indicates that the issues may be a good fit for community to help with. Requires work from eng. team Needs: Design This issue requires design work before implementating. severity-minor This label is used by an internal tool
Milestone

Comments

@Tratcher
Copy link
Member

Tratcher commented Dec 12, 2017

The new configuration APIs will read endpoints with their certificates and the default certificate. aspnet/KestrelHttpServer#2186

Here are other KestrelServerOptions to consider reading from config (Unsorted):

  • bool AddServerHeader
  • SchedulingMode ApplicationSchedulingMode
  • KestrelServerLimits Limits
    • long? MaxResponseBufferSize
    • long? MaxRequestBufferSize
    • int MaxRequestLineSize
    • int MaxRequestHeadersTotalSize
    • int MaxRequestHeaderCount
    • long? MaxRequestBodySize
    • TimeSpan KeepAliveTimeout
    • TimeSpan RequestHeadersTimeout
    • long? MaxConcurrentConnections
    • long? MaxConcurrentUpgradedConnections
    • MinDataRate MinRequestBodyDataRate
    • MinDataRate MinResponseDataRate
  • Per Endpoint ListenOptions
    • bool NoDelay
    • HttpProtocols Protocols f38f60f
  • Per Https Endpoint HttpsConnectionAdapterOptions
    • ClientCertificateMode ClientCertificateMode
    • SslProtocols SslProtocols
    • bool CheckCertificateRevocation
    • TimeSpan HandshakeTimeout

Today these must all be set in code in parallel to the configuration.

@RehanSaeed
Copy link
Contributor

RehanSaeed commented Jun 1, 2018

If anyone wants to set limits from config today, it can be done with a few extra lines of code:

.UseKestrel(
    (builderContext, options) =>
    {
        options.AddServerHeader = false;
        // Configure Kestrel from appsettings.json.
        options.Configure(builderContext.Configuration.GetSection("Kestrel"));

        // Configuring Limits from appsettings.json is not supported.
        // So we manually copy them from config.
        // See https://github.com/aspnet/KestrelHttpServer/issues/2216
        var kestrelOptions = builderContext.Configuration.GetSection<KestrelServerOptions>("Kestrel");
        foreach (var property in typeof(KestrelServerLimits).GetProperties())
        {
            var value = property.GetValue(kestrelOptions.Limits);
            property.SetValue(options.Limits, value);
        }
    })
  "Kestrel": {
    // Set stricter default limits to defend against various types of attacks.
    // See https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-2.1&tabs=aspnetcore2x#how-to-use-kestrel-in-aspnet-core-apps
    // And https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserverlimits?view=aspnetcore-2.1
    "Limits": {
      "MaxConcurrentConnections": 100, // Default is null (i.e. no maximum)
      "MaxConcurrentUpgradedConnections": 100, // Default is null (i.e. no maximum)
      "MaxRequestBodySize": 10240, // 10240 = 10KB. Default is 30MB. Use [RequestSizeLimit(100000000)] attribute to use more.
      "MaxRequestHeaderCount": 50 // Default is 100
    }
  },

@Tratcher
Copy link
Member Author

Tratcher commented Jun 1, 2018

options.Configure(builderContext.Configuration.GetSection(nameof(ApplicationOptions.Kestrel))); shouldn't be needed in that example if you're calling CreateDefaultBuilder first, it's cumulative.

@RehanSaeed
Copy link
Contributor

You're right. I'm not using it because it's too much magic for my taste but other peoples mileage may vary.

@aspnet-hello aspnet-hello transferred this issue from aspnet/KestrelHttpServer Dec 13, 2018
@aspnet-hello aspnet-hello added this to the Backlog milestone Dec 13, 2018
@aspnet-hello aspnet-hello added area-servers enhancement This issue represents an ask for new feature or an enhancement to an existing one Needs: Design This issue requires design work before implementating. feature-kestrel labels Dec 13, 2018
@stukselbax
Copy link

Any progress on issue? Will you plan to add this to WebHost.CreateDefaultBuilder() method?

@Tratcher
Copy link
Member Author

Is there any specific fields you're interested in? We haven't seen much demand.

@stukselbax
Copy link

Currently we tweaked two properties:

MinRequestBodyDataRate
MaxRequestBodySize

It is reasonable to allow configure all listed settings. Who knows where it applicable? For example, if some microservice is published, there is practically no options for maintainers of running service to change those options, if circumstances require it.

@stukselbax
Copy link

stukselbax commented Dec 29, 2018

BTW, I could not find generic method .GetSection<KestrelServerOptions>("Kestrel"), so we end up with the following (checked with 2.1.1):

UseKestrel((builderContext, options) =>
{
    var kestrelSection = builderContext.Configuration.GetSection(KestrelSectionName);
    options.Configure(kestrelSection);

    var kestrelOptions = kestrelSection.Get<KestrelServerOptions>();
    if (kestrelOptions != null)
    {
        options.AddServerHeader = kestrelOptions.AddServerHeader;
        options.AllowSynchronousIO = kestrelOptions.AllowSynchronousIO;
        options.ApplicationSchedulingMode = kestrelOptions.ApplicationSchedulingMode;
        foreach (var property in typeof(KestrelServerLimits).GetProperties())
        {
            var value = property.GetValue(kestrelOptions.Limits);
            property.SetValue(options.Limits, value);
        }
    }
});

@ffMathy
Copy link
Contributor

ffMathy commented Jan 17, 2019

I could really use this. Currently on Azure App Service with ASP .NET Core 2.2, you will get a 500.30 error on startup if you try to modify AddServerHeader to false.

Quite critical in my opinion.

@Tratcher
Copy link
Member Author

@ffMathy do you have more information on that? It's not clear why setting AddServerHeader would be a problem or how this feature would address that.

@mikkelblanne
Copy link

+1.
I was expecting this to work with all KestrelServerLimits properties, so I just added a Limits config section. It took me a while to figure out that it didn't work as expected.
My concrete need was to set MaxRequestHeadersTotalSize (internal microservice use case).

@RehanSaeed
Copy link
Contributor

The Kestrel documentation suggests that we can now set options on KestrelServerOptions from configuration. Can it do all options? Can this issue be closed?

@RehanSaeed
Copy link
Contributor

As an aside, are there any plans to add some validation attributes to the KestrelServerOptions?

@Tratcher
Copy link
Member Author

Those kestrel docs show how to read most options using the standard Options binder. We know that works for primitives like bool and int, but we should check how well it handles enums, MinDataRate, etc. before closing this.

@stukselbax
Copy link

Since MinDataRate has no settable properties - they will not be filled from configuration, because

The binder binds values to all of the public read/write properties of the type provided.

At lease properties for MinDataRate must have set;er. Also I don't really know if it should have public parameterless constructor.

Also I didn't find any notable Enum on KestrelServerOptions object graph (3.1).

Even @RehanSaeed mentioned that we can now set options on KestrelServerOptions from configuration, it requires to add some code to the application in order this to work. Why don't include it inside CreateDefaultBuilder(...)?

@Tratcher
Copy link
Member Author

Kestrel has a custom config binder that's primarily used for endpoints. Additional complex settings like MinDataRate should be added there, not in CreateDefaultBuilder.

@Tratcher Tratcher added affected-few This issue impacts only small number of customers severity-minor This label is used by an internal tool labels Oct 12, 2020 — with ASP.NET Core Issue Ranking
@drauch
Copy link

drauch commented Feb 11, 2021

What is the status of

The Kestrel documentation suggests that we can now set options on KestrelServerOptions from configuration. Can it do all options? Can this issue be closed?

It looks like in the 5.0 docs this has been removed again and we're not able to use appsettings-configuration anymore and we need to use the workaround again. Why is that the case? Is there a solution (except the Reflection-based-workaround posted above)?

Best regards,
D.R.

@Tratcher
Copy link
Member Author

The 5.0 docs were reorganized. Check here for a example showing KestrelServerOptions from config:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/options?view=aspnetcore-5.0

@drauch
Copy link

drauch commented Feb 12, 2021

Could you also elaborate a tiny bit on why this is not done automatically by the default webhost builder? Why would I not want to have these options configurable?

@Tratcher
Copy link
Member Author

This issue tracks just that, reading more from config by default. My explanation above was the historical reasoning for why we enabled endpoint config first.

Why adding this extra step exactly for this one Options class?

I don't quite follow, most Options types are not bound to config by default, you do that binding in Startup.ConfigureServices or similar. Logging is the main exception I can think of where the binding is always done for you.

@grounzero
Copy link

Are we able to set HttpsConnectionAdapterOptions.SslProtocols via appsettings.json? The docs only contain code examples.

Also, can UseConnectionLogging() be toggled via appsettings.json too?

@Tratcher
Copy link
Member Author

Tratcher commented Mar 4, 2021

Are we able to set HttpsConnectionAdapterOptions.SslProtocols via appsettings.json? The docs only contain code examples.

Yes in 5.0. The docs for that are still in progress. See #26246.

Also, can UseConnectionLogging() be toggled via appsettings.json too?

Not today, and I don't know of any issue tracking it. Is this one that you commonly enable in production? We've mainly seen it used in development environments.

The trick with UseConnectionLogging is that there are multiple places in the pipeline it could be put and you'd get different results. E.g. it could be put before or after HTTPS decryption. Both are valid for investigating different scenarios.

@davidfowl davidfowl added the help wanted Up for grabs. We would accept a PR to help resolve this issue label Mar 28, 2021
@shirhatti shirhatti modified the milestones: Backlog, .NET 7 Planning Oct 15, 2021
@shirhatti
Copy link
Contributor

Bumping into .NET 7 to reconsider

@ghost
Copy link

ghost commented Sep 13, 2022

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@deepeshhmehta
Copy link

deepeshhmehta commented Feb 16, 2023

In Program.CS

  .UseKestrel((builderContext, options) =>
  {
      var kestrelSection = builderContext.Configuration.GetSection("Kestrel");
      options.Configure(kestrelSection);

      var kestrelOptions = kestrelSection.Get<KestrelServerOptions>();
      if (kestrelOptions is not null)
      {
          options.AddServerHeader = kestrelOptions.AddServerHeader;
          options.AllowSynchronousIO = kestrelOptions.AllowSynchronousIO;
          foreach (var property in typeof(KestrelServerLimits).GetProperties())
          {
              var value = property.GetValue(kestrelOptions.Limits);
             // many properties in KestrelServerLimits are not Settable 
              if (value is not null && property.GetSetMethod() is not null)
              {
                  property.SetValue(options.Limits, value);
              }
          }
      }
  })

In appsettings.json

"Kestrel": {
    "Limits": {
      "MaxResponseBufferSize": 2048,
      "MaxRequestBufferSize": 1048576,
      "MaxRequestLineSize": 8192,
      "MaxRequestHeadersTotalSize": 32768,
      "MaxRequestHeaderCount": 100,
      "MaxRequestBodySize": 27262946,
      "KeepAliveTimeout": "0.0:5:0",
      "RequestHeadersTimeout": "0.0:5:0",
      "MaxConcurrentConnections": null,
      "MaxConcurrentUpgradedConnections": null
    },
    "AddServerHeader": true,
    "AllowResponseHeaderCompression": true,
    "AllowSynchronousIO": false,
    "AllowAlternateSchemes": false,
    "DisableStringReuse": false,
    "ConfigurationLoader": null

  }

Feel free to add more custom values and handle them using a switch case in your logic.

Another improvement I will be doing as the second iteration is to create an extention function for webBuilder and move all the logiv away from Program.cs

I will post the logic I create in the extention here, @microsoft can feel free to finetune it and ship it as an extention in .net8

@IanKemp
Copy link

IanKemp commented May 11, 2023

Can someone from Microsoft please, please, please explain to me why the MSDN docs say:

By default, Kestrel configuration is loaded from the Kestrel section using a preconfigured set of configuration providers.

yet this literally does not happen and we still, in 2023, have to use the reflection code posted here for Kestrel options to be read from configuration?

@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Jun 2, 2023
@niko-la-petrovic
Copy link

Would be nice if the official docs remarked more accurately on the current state of this.

@mkArtakMSFT mkArtakMSFT added help candidate Indicates that the issues may be a good fit for community to help with. Requires work from eng. team and removed help wanted Up for grabs. We would accept a PR to help resolve this issue labels Oct 28, 2023
@hez2010
Copy link
Contributor

hez2010 commented Nov 2, 2023

A simplified version without needs of doing reflection by yourself:

builder.WebHost.ConfigureKestrel(options =>
{
    var kestrelSection = builder.Configuration.GetSection("Kestrel");
    options.Configure(kestrelSection);
    kestrelSection.Bind(options);
});

@pinkfloydx33
Copy link

These docs include this example:

Kestrel options can also be set using a configuration provider. For example, the File Configuration Provider can load Kestrel configuration from an appsettings.json or appsettings.{Environment}.json file:

{
  "Kestrel": {
    "Limits": {
      "MaxConcurrentConnections": 100,
      "MaxConcurrentUpgradedConnections": 100
    },
    "DisableStringReuse": true
  }
}

Yet none of these settings actually bind by default. I just wasted a bunch of time trying to set Max Request Body/Line size settings from configuration which of course wasn't working. I tried the example above exactly and verified that even those don't load. I chased down the code in this repo and it looks like most configuration loading is still w/r/t ListenOptions and endpoints

amcasey added a commit to dotnet/AspNetCore.Docs that referenced this issue Jan 31, 2024
Presently, they can't conveniently be configured from appsettings.json.  There are [workarounds](dotnet/aspnetcore#4765), but none that seem worth recommending.

Fixes #31108
@Ghostbird
Copy link

Ghostbird commented Feb 7, 2024

I'd love to see this too. Today a customer ran into a maximum file upload size issue. If this had been working, I could have seamlessly fixed this in a minute. Now I have to deploy a new production version of the API.

UPDATE: The code by @hez2010 works very nicely. Now we don't need to a code change if we need to alter these parameters again.

I made one change, I used the overload of ConfigureKestrel that injects the WebHostBuilderContext so it can be used fluently. Our program code looks like this:

Host
.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults((webBuilder) => webBuilder
  .UseStartup<Foo>()
  .ConfigureKestrel((context, options) =>
  {
    var kestrelSection = context.Configuration.GetSection("Kestrel");
    options.Configure(kestrelSection);
    kestrelSection.Bind(options);
  })
)
.Build()
.Run();

@amcasey amcasey modified the milestones: .NET 8 Planning, Backlog Feb 14, 2024
@houbi56
Copy link

houbi56 commented May 22, 2024

Are we able to set HttpsConnectionAdapterOptions.SslProtocols via appsettings.json? The docs only contain code examples.

Yes in 5.0. The docs for that are still in progress. See #26246.

Also, can UseConnectionLogging() be toggled via appsettings.json too?

Not today, and I don't know of any issue tracking it. Is this one that you commonly enable in production? We've mainly seen it used in development environments.

The trick with UseConnectionLogging is that there are multiple places in the pipeline it could be put and you'd get different results. E.g. it could be put before or after HTTPS decryption. Both are valid for investigating different scenarios.

This is an important scenario for us when deploying apps in customers environment. Specifically, enabling connection logging/tracing in a running app.
It seems that the configuration was developed code first instead of configuration first.
Options only configurable through code requires a recompile and deployment.

Could we see a change of direction here for NET 9 where appsettings is a first class citizen?

@hez2010
Copy link
Contributor

hez2010 commented May 22, 2024

Today a customer ran into a maximum file upload size issue

As for file uploading (through multipart-form), it is limited by another options called FormOptions, which need to be configured separately.

@Ghostbird
Copy link

Ghostbird commented May 22, 2024

Today a customer ran into a maximum file upload size issue

As for file uploading (through multipart-form), it is limited by another options called FormOptions, which need to be configured separately.

Good to know. We didn't run into this in our case, since it's a ReST-ish POST to our web API where the file upload data is the request body itself and the necessary metadata is part of the URI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affected-few This issue impacts only small number of customers area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-kestrel help candidate Indicates that the issues may be a good fit for community to help with. Requires work from eng. team Needs: Design This issue requires design work before implementating. severity-minor This label is used by an internal tool
Projects
None yet
Development

No branches or pull requests