Read KestrelServerOptions and limits from configuration - #69340
marcominerva wants to merge 3 commits into
Conversation
|
Thanks for your PR, @marcominerva. Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
There was a problem hiding this comment.
🟡 Changes recommended
Two unresolved moderate configuration-validation issues must be addressed before approval.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds trim-friendly Kestrel configuration binding for server options and limits while preserving code-over-configuration precedence and endpoint-only reload behavior.
Changes:
- Adds manual binding for server flags, limits, HTTP/2, HTTP/3, and data rates.
- Applies binding during loader construction and preserves endpoint-only reloads.
- Adds tests, documentation, and configuration error messages.
Two unresolved moderate findings remain in ServerOptionsConfigurationBinder.cs: empty strings may be treated as null instead of rejected (1 vote), and scalar MinRequestBodyDataRate values may be silently ignored (3 votes).
File summaries
| File | Summary |
|---|---|
src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs |
Tests binding, parsing, precedence, null handling, and reload behavior. |
src/Servers/Kestrel/Core/src/KestrelServerOptions.cs |
Documents configuration timing, precedence, and reload semantics. |
src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs |
Applies server-option binding during construction and limits reloads to endpoints. |
src/Servers/Kestrel/Core/src/Internal/ServerOptionsConfigurationBinder.cs |
Implements manual binding; contains the two unresolved moderate findings. |
src/Servers/Kestrel/Core/src/CoreStrings.resx |
Adds configuration error messages. |
Review details
Suppressed comments (1)
src/Servers/Kestrel/Core/src/Internal/ServerOptionsConfigurationBinder.cs:220
IConfigurationpreserves an empty string as a configured value, so convertingstring.Emptytonullmakes values such asLimits:MaxRequestHeaderCount: ""silently retain their existing option instead of reaching the parser and throwing the requiredInvalidOperationExceptionfor an unparsable value. Please distinguish an explicitnullfrom an empty string (including the nullableMinDataRateparent case).
value = configuration[key];
if (string.IsNullOrEmpty(value))
{
value = null;
}
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Only endpoints, certificates and endpoint defaults were read from the Kestrel configuration section. Everything else had to be set in code, so apps that wanted to tune limits from
appsettings.jsonresorted to reflection-based workarounds copying properties off a bound instance.Add
ServerOptionsConfigurationBinder, a hand-written binder (no reflection, so it stays trim/AOT friendly) covering the non-endpoint part of the section:MaxConcurrentUpgradedConnections, MinRequestBodyDataRate and MinResponseDataRate
Binding rules:
InvalidOperationExceptionnaming the configuration path, and an out-of-range value still throws from the property setter.MinDataRatesection may specify onlyBytesPerSecondor onlyGracePeriod: the unspecified half is taken from the value the option already has. If that value is null, because the rate was disabled, there is nothing to fall back on and the missing half throws.Configuration does not win over code. The binder runs from the
KestrelConfigurationLoaderconstructor, i.e. while theIConfigureOptions<KestrelServerOptions>pipeline is still executing, so aservices.Configure<KestrelServerOptions>delegate registered after the one that callsConfigure(IConfiguration)overwrites what was bound.Reload keeps re-reading endpoints only, so a configuration change cannot clobber values the app set in code.
Fixes #4765