Skip to content

Commit 4ebf695

Browse files
authored
Fix NRE in KestrelServerOptions.Listen*() (#21467)
* Fix NRE in KestrelServerOptions.Listen*() * Fix tests
1 parent c9ce066 commit 4ebf695

File tree

4 files changed

+26
-10
lines changed

4 files changed

+26
-10
lines changed

src/Servers/Kestrel/Core/src/Internal/ConfigurationReader.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,20 @@ internal class ConfigurationReader
1919

2020
private readonly IConfiguration _configuration;
2121

22+
private IDictionary<string, CertificateConfig> _certificates;
23+
private EndpointDefaults _endpointDefaults;
24+
private IEnumerable<EndpointConfig> _endpoints;
25+
private bool? _latin1RequestHeaders;
26+
2227
public ConfigurationReader(IConfiguration configuration)
2328
{
2429
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
25-
Certificates = ReadCertificates();
26-
EndpointDefaults = ReadEndpointDefaults();
27-
Endpoints = ReadEndpoints();
28-
Latin1RequestHeaders = _configuration.GetValue<bool>(Latin1RequestHeadersKey);
2930
}
3031

31-
public IDictionary<string, CertificateConfig> Certificates { get; }
32-
public EndpointDefaults EndpointDefaults { get; }
33-
public IEnumerable<EndpointConfig> Endpoints { get; }
34-
public bool Latin1RequestHeaders { get; }
32+
public IDictionary<string, CertificateConfig> Certificates => _certificates ??= ReadCertificates();
33+
public EndpointDefaults EndpointDefaults => _endpointDefaults ??= ReadEndpointDefaults();
34+
public IEnumerable<EndpointConfig> Endpoints => _endpoints ??= ReadEndpoints();
35+
public bool Latin1RequestHeaders => _latin1RequestHeaders ??= _configuration.GetValue<bool>(Latin1RequestHeadersKey);
3536

3637
private IDictionary<string, CertificateConfig> ReadCertificates()
3738
{

src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ internal KestrelConfigurationLoader(KestrelServerOptions options, IConfiguration
2929
Options = options ?? throw new ArgumentNullException(nameof(options));
3030
Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
3131
ReloadOnChange = reloadOnChange;
32+
33+
ConfigurationReader = new ConfigurationReader(configuration);
3234
}
3335

3436
public KestrelServerOptions Options { get; }

src/Servers/Kestrel/Core/test/KestrelServerOptionsTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,16 @@ public void ConfigureEndpointDefaultsAppliesToNewEndpoints()
4949
});
5050
Assert.Equal(HttpProtocols.Http2, options.CodeBackedListenOptions[3].Protocols);
5151
}
52+
53+
[Fact]
54+
public void CanCallListenAfterConfigure()
55+
{
56+
var options = new KestrelServerOptions();
57+
options.Configure();
58+
59+
// This is a regression test to verify the Listen* methods don't throw a NullReferenceException if called after Configure().
60+
// https://github.com/dotnet/aspnetcore/issues/21423
61+
options.ListenLocalhost(5000);
62+
}
5263
}
5364
}

src/Servers/Kestrel/Kestrel/test/ConfigurationReaderTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ public void ReadEndpointWithMissingUrl_Throws()
9797
{
9898
new KeyValuePair<string, string>("Endpoints:End1", ""),
9999
}).Build();
100-
Assert.Throws<InvalidOperationException>(() => new ConfigurationReader(config));
100+
var reader = new ConfigurationReader(config);
101+
Assert.Throws<InvalidOperationException>(() => reader.Endpoints);
101102
}
102103

103104
[Fact]
@@ -107,7 +108,8 @@ public void ReadEndpointWithEmptyUrl_Throws()
107108
{
108109
new KeyValuePair<string, string>("Endpoints:End1:Url", ""),
109110
}).Build();
110-
Assert.Throws<InvalidOperationException>(() => new ConfigurationReader(config));
111+
var reader = new ConfigurationReader(config);
112+
Assert.Throws<InvalidOperationException>(() => reader.Endpoints);
111113
}
112114

113115
[Fact]

0 commit comments

Comments
 (0)