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.
using System;
@ -15,9 +15,10 @@ namespace Microsoft.AspNetCore.HttpsPolicy
{
public class HttpsRedirectionMiddleware
{
private const int PortNotFound = -1;
private readonly RequestDelegate _next;
private bool _portEvaluated = false;
private int? _httpsPort;
private readonly Lazy<int> _httpsPort;
private readonly int _statusCode;
private readonly IServerAddressesFeature _serverAddressesFeature;
@ -42,8 +43,14 @@ namespace Microsoft.AspNetCore.HttpsPolicy
throw new ArgumentNullException(nameof(options));
}
var httpsRedirectionOptions = options.Value;
_httpsPort = httpsRedirectionOptions.HttpsPort;
_portEvaluated = _httpsPort.HasValue;
if (httpsRedirectionOptions.HttpsPort.HasValue)
{
_httpsPort = new Lazy<int>(() => httpsRedirectionOptions.HttpsPort.Value);
}
else
{
_httpsPort = new Lazy<int>(TryGetHttpsPort);
}
_statusCode = httpsRedirectionOptions.RedirectStatusCode;
_logger = loggerFactory.CreateLogger<HttpsRedirectionMiddleware>();
}
@ -70,7 +77,13 @@ namespace Microsoft.AspNetCore.HttpsPolicy
/// <returns></returns>
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);
}
@ -101,7 +114,8 @@ namespace Microsoft.AspNetCore.HttpsPolicy
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,
// Order for finding the HTTPS port:
@ -109,59 +123,47 @@ namespace Microsoft.AspNetCore.HttpsPolicy
// 2. HTTPS_PORT environment variable
// 3. IServerAddressesFeature
// 4. Fail if not set
port = -1;
if (_portEvaluated)
var nullablePort = _config.GetValue<int?>("HTTPS_PORT");
if (nullablePort.HasValue)
{
port = _httpsPort ?? port;
return _httpsPort.HasValue;
}
_portEvaluated = true;
_httpsPort = _config.GetValue<int?>("HTTPS_PORT");
if (_httpsPort.HasValue)
{
port = _httpsPort.Value;
var port = nullablePort.Value;
_logger.PortLoadedFromConfig(port);
return true;
return port;
}
if (_serverAddressesFeature == null)
{
_logger.FailedToDeterminePort();
return false;
return PortNotFound;
}
int? httpsPort = null;
foreach (var address in _serverAddressesFeature.Addresses)
{
var bindingAddress = BindingAddress.Parse(address);
if (bindingAddress.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
{
// If we find multiple different https ports specified, throw
if (httpsPort.HasValue && httpsPort != bindingAddress.Port)
if (nullablePort.HasValue && nullablePort != bindingAddress.Port)
{
_logger.FailedMultiplePorts();
return false;
return PortNotFound;
}
else
{
httpsPort = bindingAddress.Port;
nullablePort = bindingAddress.Port;
}
}
}
if (httpsPort.HasValue)
if (nullablePort.HasValue)
{
_httpsPort = httpsPort;
port = _httpsPort.Value;
var port = nullablePort.Value;
_logger.PortFromServer(port);
return true;
return port;
}
_logger.FailedToDeterminePort();
return false;
return PortNotFound;
}
}
}