Lazyily initialize Https port in HttpsRedirectionMiddleware

This commit is contained in:
Justin Kotalik 2019-08-07 09:49:27 -07:00 committed by Kevin Pilch
parent c3af33a023
commit 78b46768d7
1 changed files with 33 additions and 31 deletions

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
@ -15,9 +15,10 @@ namespace Microsoft.AspNetCore.HttpsPolicy
{ {
public class HttpsRedirectionMiddleware public class HttpsRedirectionMiddleware
{ {
private const int PortNotFound = -1;
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private bool _portEvaluated = false; private readonly Lazy<int> _httpsPort;
private int? _httpsPort;
private readonly int _statusCode; private readonly int _statusCode;
private readonly IServerAddressesFeature _serverAddressesFeature; private readonly IServerAddressesFeature _serverAddressesFeature;
@ -42,8 +43,14 @@ namespace Microsoft.AspNetCore.HttpsPolicy
throw new ArgumentNullException(nameof(options)); throw new ArgumentNullException(nameof(options));
} }
var httpsRedirectionOptions = options.Value; var httpsRedirectionOptions = options.Value;
_httpsPort = httpsRedirectionOptions.HttpsPort; if (httpsRedirectionOptions.HttpsPort.HasValue)
_portEvaluated = _httpsPort.HasValue; {
_httpsPort = new Lazy<int>(() => httpsRedirectionOptions.HttpsPort.Value);
}
else
{
_httpsPort = new Lazy<int>(TryGetHttpsPort);
}
_statusCode = httpsRedirectionOptions.RedirectStatusCode; _statusCode = httpsRedirectionOptions.RedirectStatusCode;
_logger = loggerFactory.CreateLogger<HttpsRedirectionMiddleware>(); _logger = loggerFactory.CreateLogger<HttpsRedirectionMiddleware>();
} }
@ -70,7 +77,13 @@ namespace Microsoft.AspNetCore.HttpsPolicy
/// <returns></returns> /// <returns></returns>
public Task Invoke(HttpContext context) public Task Invoke(HttpContext context)
{ {
if (context.Request.IsHttps || !TryGetHttpsPort(out var port)) if (context.Request.IsHttps)
{
return _next(context);
}
var port = _httpsPort.Value;
if (port == PortNotFound)
{ {
return _next(context); return _next(context);
} }
@ -101,7 +114,8 @@ namespace Microsoft.AspNetCore.HttpsPolicy
return Task.CompletedTask; return Task.CompletedTask;
} }
private bool TryGetHttpsPort(out int port) // Returns PortNotFound (-1) if we were unable to determine the port.
private int TryGetHttpsPort()
{ {
// The IServerAddressesFeature will not be ready until the middleware is Invoked, // The IServerAddressesFeature will not be ready until the middleware is Invoked,
// Order for finding the HTTPS port: // Order for finding the HTTPS port:
@ -109,59 +123,47 @@ namespace Microsoft.AspNetCore.HttpsPolicy
// 2. HTTPS_PORT environment variable // 2. HTTPS_PORT environment variable
// 3. IServerAddressesFeature // 3. IServerAddressesFeature
// 4. Fail if not set // 4. Fail if not set
var nullablePort = _config.GetValue<int?>("HTTPS_PORT");
port = -1; if (nullablePort.HasValue)
if (_portEvaluated)
{ {
port = _httpsPort ?? port; var port = nullablePort.Value;
return _httpsPort.HasValue;
}
_portEvaluated = true;
_httpsPort = _config.GetValue<int?>("HTTPS_PORT");
if (_httpsPort.HasValue)
{
port = _httpsPort.Value;
_logger.PortLoadedFromConfig(port); _logger.PortLoadedFromConfig(port);
return true; return port;
} }
if (_serverAddressesFeature == null) if (_serverAddressesFeature == null)
{ {
_logger.FailedToDeterminePort(); _logger.FailedToDeterminePort();
return false; return PortNotFound;
} }
int? httpsPort = null;
foreach (var address in _serverAddressesFeature.Addresses) foreach (var address in _serverAddressesFeature.Addresses)
{ {
var bindingAddress = BindingAddress.Parse(address); var bindingAddress = BindingAddress.Parse(address);
if (bindingAddress.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase)) if (bindingAddress.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
{ {
// If we find multiple different https ports specified, throw // If we find multiple different https ports specified, throw
if (httpsPort.HasValue && httpsPort != bindingAddress.Port) if (nullablePort.HasValue && nullablePort != bindingAddress.Port)
{ {
_logger.FailedMultiplePorts(); _logger.FailedMultiplePorts();
return false; return PortNotFound;
} }
else else
{ {
httpsPort = bindingAddress.Port; nullablePort = bindingAddress.Port;
} }
} }
} }
if (httpsPort.HasValue) if (nullablePort.HasValue)
{ {
_httpsPort = httpsPort; var port = nullablePort.Value;
port = _httpsPort.Value;
_logger.PortFromServer(port); _logger.PortFromServer(port);
return true; return port;
} }
_logger.FailedToDeterminePort(); _logger.FailedToDeterminePort();
return false; return PortNotFound;
} }
} }
} }